Этот код для последовательности collatz в python хорош? [Дубликат]

Это мой код для GridView с Button + Textview

public View getView(final int position, View convertView, ViewGroup parent) {
        LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.grid_item, null);  
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        TextView text = (TextView)convertView.findViewById(R.id.texto_grid);
        text.setText(app_listaActiva_NOMBRES[position]);
        Button image = (Button)convertView.findViewById(R.id.miniatura_grid);
        image.setBackgroundResource(R.drawable.custom_button);
        image.setOnClickListener(new MyOnClickListener2(position,app_listaActiva_SONIDOS));
        return convertView;
    }
416
задан 9 revs, 6 users 72% 22 March 2017 в 17:13
поделиться

13 ответов

Самый простой способ добиться этого - поместить метод input в цикл while. Используйте continue , когда вы получаете плохой ввод, и break выходят из цикла, когда вы удовлетворены.

Когда ваш вход может привести к исключению

Попробуйте попытаться и поймать , чтобы определить, когда пользователь вводит данные, которые не могут быть проанализированы.

while True:
    try:
        # Note: Python 2.x users should use raw_input, the equivalent of 3.x's input
        age = int(input("Please enter your age: "))
    except ValueError:
        print("Sorry, I didn't understand that.")
        #better try again... Return to the start of the loop
        continue
    else:
        #age was successfully parsed!
        #we're ready to exit the loop.
        break
if age >= 18: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")

Реализация собственных правил проверки

Если вы хотите отклонить значения, которые Python может успешно проанализировать, вы можете добавить свою собственную логику проверки.

while True:
    data = input("Please enter a loud message (must be all caps): ")
    if not data.isupper():
        print("Sorry, your response was not loud enough.")
        continue
    else:
        #we're happy with the value given.
        #we're ready to exit the loop.
        break

while True:
    data = input("Pick an answer from A to D:")
    if data.lower() not in ('a', 'b', 'c', 'd'):
        print("Not an appropriate choice.")
    else:
        break

Объединение обработки исключений и пользовательской проверки

Оба вышеуказанных метода могут быть объединены в один цикл.

while True:
    try:
        age = int(input("Please enter your age: "))
    except ValueError:
        print("Sorry, I didn't understand that.")
        continue

    if age < 0:
        print("Sorry, your response must not be negative.")
        continue
    else:
        #age was successfully parsed, and we're happy with its value.
        #we're ready to exit the loop.
        break
if age >= 18: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")

Инкапсулирование его в функции

Если вам нужно спросить у вашего пользователя множество разных значений, может быть полезно поместить этот код в функция, поэтому вам не нужно повторно указывать ее каждый раз.

def get_non_negative_int(prompt):
    while True:
        try:
            value = int(input(prompt))
        except ValueError:
            print("Sorry, I didn't understand that.")
            continue

        if value < 0:
            print("Sorry, your response must not be negative.")
            continue
        else:
            break
    return value

age = get_non_negative_int("Please enter your age: ")
kids = get_non_negative_int("Please enter the number of children you have: ")
salary = get_non_negative_int("Please enter your yearly earnings, in dollars: ")

Вводя все вместе

Вы можете расширить эту идею, чтобы создать очень общую функцию ввода:

def sanitised_input(prompt, type_=None, min_=None, max_=None, range_=None):
    if min_ is not None and max_ is not None and max_ < min_:
        raise ValueError("min_ must be less than or equal to max_.")
    while True:
        ui = input(prompt)
        if type_ is not None:
            try:
                ui = type_(ui)
            except ValueError:
                print("Input type must be {0}.".format(type_.__name__))
                continue
        if max_ is not None and ui > max_:
            print("Input must be less than or equal to {0}.".format(max_))
        elif min_ is not None and ui < min_:
            print("Input must be greater than or equal to {0}.".format(min_))
        elif range_ is not None and ui not in range_:
            if isinstance(range_, range):
                template = "Input must be between {0.start} and {0.stop}."
                print(template.format(range_))
            else:
                template = "Input must be {0}."
                if len(range_) == 1:
                    print(template.format(*range_))
                else:
                    print(template.format(" or ".join((", ".join(map(str,
                                                                     range_[:-1])),
                                                       str(range_[-1])))))
        else:
            return ui

С использованием, например:

age = sanitised_input("Enter your age: ", int, 1, 101)
answer = sanitised_input("Enter your answer: ", str.lower, range_=('a', 'b', 'c', 'd'))

Общие ошибки, и почему вы должны избегать их

Резервное использование красного undant input Заявления

Этот метод работает, но обычно считается неудовлетворительным:

data = input("Please enter a loud message (must be all caps): ")
while not data.isupper():
    print("Sorry, your response was not loud enough.")
    data = input("Please enter a loud message (must be all caps): ")

Первоначально он может выглядеть привлекательно, потому что он короче, чем метод while True, но он нарушает Не повторяйте сам принцип разработки программного обеспечения. Это увеличивает вероятность ошибок в вашей системе. Что делать, если вы хотите выполнить резервное копирование до 2.7, изменив input на raw_input, но случайно измените только первый input выше?

Рекурсия будет бить ваш стек

Если вы только что узнали о рекурсии, возможно, у вас возникнет соблазн использовать ее в get_non_negative_int, поэтому вы можете избавиться от цикла while.

def get_non_negative_int(prompt):
    try:
        value = int(input(prompt))
    except ValueError:
        print("Sorry, I didn't understand that.")
        return get_non_negative_int(prompt)

    if value < 0:
        print("Sorry, your response must not be negative.")
        return get_non_negative_int(prompt)
    else:
        return value

Кажется, что он работает отлично в большинстве случаев, но если пользователь вводит неверные данные достаточно времени, сценарий заканчивается с помощью RuntimeError: maximum recursion depth exceeded. Вы можете подумать, что «ни один дурак не допустит 1000 ошибок подряд», но вы недооцениваете изобретательность дураков!

494
ответ дан 6 revs, 4 users 75% 15 August 2018 в 21:32
поделиться
  • 1
    Его забава читает его со многими примерами. Недооцененный урок: «Не стоит недооценивать изобретательность дураков!» – Pet Ibaño 3 January 2017 в 03:02
  • 2
    Я бы не только поддержал и Q & amp; A в любом случае, так как они великолепны, но вы опечатали сделку «шестьдесят шесть». Хорошо, @ Кевин. – erekalper 2 February 2018 в 16:58
  • 3
    Очень полное объяснение - спасибо! – MJM 24 July 2018 в 10:54

Хотя блок try / except будет работать, гораздо более быстрый и чистый способ выполнить эту задачу будет состоять в использовании str.isdigit().

while True:
    age = input("Please enter your age: ")
    if age.isdigit():
        age = int(age)
        break
    else:
        print("Invalid number '{age}'. Try again.".format(age=age))

if age >= 18: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")
0
ответ дан 2 revs 15 August 2018 в 21:32
поделиться
  • 1
    str.isnumeric доступен только в Python 3 и не возвращает true для всех действительных целых чисел. Подобно str.isdigit, он проверяет свойства символов, а - не является числовым символом. – Martijn Pieters♦ 6 June 2016 в 06:50

Зачем вы делаете while True, а затем выходите из этого цикла, в то время как вы также можете просто поместить свои требования в оператор while, поскольку все, что вы хотите, останавливается, когда у вас есть возраст?

age = None
while age is None:
    input_value = input("Please enter your age: ")
    try:
        # try and convert the string input to a number
        age = int(input_value)
    except ValueError:
        # tell the user off
        print("{input} is not a number, please enter a number only".format(input=input_value))
if age >= 18:
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")

Это приведет к следующему:

Please enter your age: *potato*
potato is not a number, please enter a number only
Please enter your age: *5*
You are not able to vote in the United States.

это будет работать, поскольку возраст никогда не будет иметь значения, которое не имеет смысла, а код следует логике вашего «бизнес-процесса»

21
ответ дан 2 revs, 2 users 96% 15 August 2018 в 21:32
поделиться

Итак, я недавно возился с чем-то похожим на это, и я придумал следующее решение, которое использует способ ввода ввода, который отклоняет нежелательный файл, прежде чем он будет проверен любым логическим способом.

read_single_keypress() любезность https://stackoverflow.com/a/6599441/4532996

def read_single_keypress() -> str:
    """Waits for a single keypress on stdin.
    -- from :: https://stackoverflow.com/a/6599441/4532996
    """

    import termios, fcntl, sys, os
    fd = sys.stdin.fileno()
    # save old state
    flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
    attrs_save = termios.tcgetattr(fd)
    # make raw - the way to do this comes from the termios(3) man page.
    attrs = list(attrs_save) # copy the stored version to update
    # iflag
    attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
                  | termios.ISTRIP | termios.INLCR | termios. IGNCR
                  | termios.ICRNL | termios.IXON )
    # oflag
    attrs[1] &= ~termios.OPOST
    # cflag
    attrs[2] &= ~(termios.CSIZE | termios. PARENB)
    attrs[2] |= termios.CS8
    # lflag
    attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
                  | termios.ISIG | termios.IEXTEN)
    termios.tcsetattr(fd, termios.TCSANOW, attrs)
    # turn off non-blocking
    fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
    # read a single keystroke
    try:
        ret = sys.stdin.read(1) # returns a single character
    except KeyboardInterrupt:
        ret = 0
    finally:
        # restore old state
        termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
        fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
    return ret

def until_not_multi(chars) -> str:
    """read stdin until !(chars)"""
    import sys
    chars = list(chars)
    y = ""
    sys.stdout.flush()
    while True:
        i = read_single_keypress()
        _ = sys.stdout.write(i)
        sys.stdout.flush()
        if i not in chars:
            break
        y += i
    return y

def _can_you_vote() -> str:
    """a practical example:
    test if a user can vote based purely on keypresses"""
    print("can you vote? age : ", end="")
    x = int("0" + until_not_multi("0123456789"))
    if not x:
        print("\nsorry, age can only consist of digits.")
        return
    print("your age is", x, "\nYou can vote!" if x >= 18 else "Sorry! you can't vote")

_can_you_vote()

Здесь вы можете найти полный модуль здесь .

Пример:

$ ./input_constrain.py
can you vote? age : a
sorry, age can only consist of digits.
$ ./input_constrain.py 
can you vote? age : 23<RETURN>
your age is 23
You can vote!
$ _

Обратите внимание, что природа этой реализации заключается в том, что она закрывает stdin, как только считывается что-то, что не является цифрой. Я не попал в enter после a, но мне нужно было после чисел.

Вы можете объединить это с функцией thismany() в том же модуле, чтобы разрешить, скажем, три цифры.

8
ответ дан 3 revs 15 August 2018 в 21:32
поделиться

Используйте оператор while, пока пользователь не вводит истинное значение, и если входное значение не является числом или это значение null, пропустите его и попробуйте снова и так далее. В примере я попытался ответить на действительно ваш вопрос. Если мы предположим, что наш возраст составляет от 1 до 150, тогда принимается входное значение, иначе это неправильное значение. Для завершения программы пользователь может использовать клавишу 0 и вводить ее как значение.

Примечание: прочитайте комментарии вверху кода.

# If your input value is only a number then use "Value.isdigit() == False".
# If you need an input that is a text, you should remove "Value.isdigit() == False".
def Input(Message):
    Value = None
    while Value == None or Value.isdigit() == False:
        try:        
            Value = str(input(Message)).strip()
        except InputError:
            Value = None
    return Value

# Example:
age = 0
# If we suppose that our age is between 1 and 150 then input value accepted,
# else it's a wrong value.
while age <=0 or age >150:
    age = int(Input("Please enter your age: "))
    # For terminating program, the user can use 0 key and enter it as an a value.
    if age == 0:
        print("Terminating ...")
        exit(0)

if age >= 18 and age <=150: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")
1
ответ дан 5 revs 15 August 2018 в 21:32
поделиться

Хотя принятый ответ потрясающий. Я также хотел бы поделиться быстрым взломом для этой проблемы. (Это также заботится об отрицательной возрастной проблеме.)

f=lambda age: (age.isdigit() and ((int(age)>=18  and "Can vote" ) or "Cannot vote")) or \
f(raw_input("invalid input. Try again\nPlease enter your age: "))
print f(raw_input("Please enter your age: "))

P.S. Этот код предназначен для python 2.x и может быть экспортирован в 3.x путем изменения функций raw_input и печати. ​​

13
ответ дан aaveg 15 August 2018 в 21:32
поделиться
  • 1
    Обратите внимание, что этот код рекурсивный, но здесь не требуется рекурсия, и, как сказал Кевин, он может взорвать ваш стек. – PM 2Ring 31 January 2016 в 09:12
  • 2
    @ PM2Ring - вы правы. Но моя цель здесь состояла в том, чтобы показать, как «короткое замыкание» может свести к минимуму (украсить) длинные фрагменты кода. – aaveg 3 February 2016 в 09:58
  • 3
    Зачем вам назначать лямбду переменной, просто используйте def. def f(age): намного яснее, чем f = lambda age: – GP89 16 May 2017 в 22:29
  • 4
    В некоторых случаях вам может понадобиться возраст только один раз, а затем использовать эту функцию не нужно. Можно захотеть использовать функцию и выбросить ее после выполнения задания. Кроме того, это может быть не самый лучший способ, но это определенно другой способ сделать это (что было целью моего решения). – aaveg 16 May 2017 в 23:17
  • 5
    интересный POV! – MJM 24 July 2018 в 10:55

Использовать try catch с бесконечным циклом while. Чтобы проверить пустую строку, используйте инструкцию IF, чтобы проверить, является ли строка пустой.

while True:
    name = input("Enter Your Name\n")
    if not name:
        print("I did not understood that")
        continue
    else:
        break

while True:
    try:
        salary = float(input("whats ur salary\n"))
    except ValueError:
        print("I did not understood that")
        continue
    else:
        break

while True:
    try:
        print("whats ur age?")
        age = int(float(input()))
    except ValueError:
        print("I did not understood that")
        continue
    else:
        break

print("Hello "+ name +  "\nYour salary is " + str(salary) + '\nand you will be ' + str(age+1) +' in a Year')
0
ответ дан Mahesh Sonavane 15 August 2018 в 21:32
поделиться

Вы можете написать более общую логику, чтобы позволить пользователю вводить только определенное количество раз, поскольку один и тот же вариант использования возникает во многих реальных приложениях.

def getValidInt(iMaxAttemps = None):
  iCount = 0
  while True:
    # exit when maximum attempt limit has expired
    if iCount != None and iCount > iMaxAttemps:
       return 0     # return as default value

    i = raw_input("Enter no")
    try:
       i = int(i)
    except ValueError as e:
       print "Enter valid int value"
    else:
       break

    return i

age = getValidInt()
# do whatever you want to do.
1
ответ дан Mangu Singh Rajpurohit 15 August 2018 в 21:32
поделиться
  • 1
    вы забудете увеличить значение iCount после каждого цикла – Hoai-Thu Vuong 1 March 2017 в 09:49
def validate_age(age):
    if age >=0 :
        return True
    return False

while True:
    try:
        age = int(raw_input("Please enter your age:"))
        if validate_age(age): break
    except ValueError:
        print "Error: Invalid age."
2
ответ дан ojas mohril 15 August 2018 в 21:32
поделиться

Попробуйте следующее: -

def takeInput(required):
  print 'ooo or OOO to exit'
  ans = raw_input('Enter: ')

  if not ans:
      print "You entered nothing...!"
      return takeInput(required) 

      ##  FOR Exit  ## 
  elif ans in ['ooo', 'OOO']:
    print "Closing instance."
    exit()

  else:
    if ans.isdigit():
      current = 'int'
    elif set('[~!@#$%^&*()_+{}":/\']+$').intersection(ans):
      current = 'other'
    elif isinstance(ans,basestring):
      current = 'str'        
    else:
      current = 'none'

  if required == current :
    return ans
  else:
    return takeInput(required)

## pass the value in which type you want [str/int/special character(as other )]
print "input: ", takeInput('str')
2
ответ дан Pratik Anand 15 August 2018 в 21:32
поделиться

Вы можете сделать оператор ввода while True loop, чтобы он неоднократно запрашивал вход пользователя и затем прерывал этот цикл, если пользователь вводит ответ, который вам нужен. И вы можете использовать try и except blocks для обработки недействительных ответов.

while True:

    var = True

    try:
        age = int(input("Please enter your age: "))

    except ValueError:
        print("Invalid input.")
        var = False

    if var == True:
        if age >= 18:
                print("You are able to vote in the United States.")
                break
        else:
            print("You are not able to vote in the United States.")

Переменная var такова, что если пользователь вводит строку вместо целого, программа не будет возвращать «Вы не можете голосовать в Соединенных Штатах ».

0
ответ дан user9142415 15 August 2018 в 21:32
поделиться

Чтобы отредактировать код и исправить ошибку:

while True:
    try:
       age = int(input("Please enter your age: "))
       if age >= 18: 
           print("You are able to vote in the United States!")
           break
       else:
           print("You are not able to vote in the United States.")
           break
    except ValueError:
       print("Please enter a valid response")
2
ответ дан ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000 15 August 2018 в 21:32
поделиться
0
ответ дан Ray Hu 29 October 2018 в 04:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: