В главе 3 книги Автоматизируйте скучную работу с Python Автор Al Sweigart, в одном упражнении предлагается написать программу, которая выполняет последовательность Коллатца.
Сначала я написал базовую версию, а затем добавил и реструктурировал некоторые из них, чтобы учесть неверный ввод. Приветствуются любые мысли или критические замечания, направленные на то, чтобы сделать его более кратким, организованным или разборчивым.
def collatz(number): # This evaluates and prints the sequence of numbers.
if number % 2 == 0: # If it's an even number.
print(number // 2)
return number // 2
else: # If it's an odd number.
print(3 * number + 1)
return 3 * number + 1
def main(): # The main loop inside a function so the ValueError message can appear as many times as needed.
try:
user_input = int(input())
while user_input > 1:
user_input = collatz(user_input)
if user_input <= 0: # If a negative integer is entered.
print('Please enter a positive integer.')
else:
print('Enter another integer.')
except ValueError: # If something other than an integer is entered.
print('Please enter a valid integer.')
print('Type any positive integer.') # Main prompt.
while True: # This calls the main loop so you can repeat the equation as many times as needed.
main()
1 ответ
Большая часть вашего кода связана с получением и проверкой пользовательского ввода. Это утомительный код для написания и поддержки. Кроме того, программы, основанные на взаимодействии с пользователем, трудно выполнять во время разработки, тестирования и отладки: каждое выполнение требует ручного диалога между пользователем (вами, программистом) и компьютером. Это очень быстро надоедает. Более того, в вашей программе нет чистого способа бросить курить. Более мощный подход, основанный на аргументах командной строки и встроенных argparse
библиотека показана ниже.
Вторая проблема заключается в том, что ваш collatz()
функция смешивает алгоритмические вычисления и отчеты (например, печать). Это почти всегда плохая идея. Более гибкий подход — ограничить collatz()
чисто к алгоритму и делать печать на более высоком уровне в программе — либо в
main()
, если отчет остается предельно простым, или в вызываемой им функции.
Суть большинства этих предложений заключается в более тщательной организации кода, чтобы различные задачи были более разделены: сбор данных, вводимых пользователем; проверка ввода; вычисление; и отчетность.
import argparse
import sys
def main(args):
# Get user arguments.
opts = parse_args(args)
# Make computations.
sequences = [list(collatz(val)) for val in opts.initial_values]
# Report to user. Enhance as needed.
for seq in sequences:
print(seq)
def parse_args(args):
# You want the user to provide one or more integers
# on the command line. The argparse library will handle that
# automatically for many use cases (e.g, any integer). In your situation,
# you do need to write a type validation function, but that process
# is a bit simpler and more focused than your previous validation
# code, which was mixed with the rest of the program's logic.
ap = argparse.ArgumentParser()
ap.add_argument('initial_values', nargs="+", type = positive_int)
return ap.parse_args(args)
def positive_int(val):
# You can make this more robust if needed (eg to prevent values like
# '12.34' from being accepted), but here's the basic technique.
try:
n = int(val)
assert n > 0
return n
except Exception:
raise argparse.ArgumentTypeError(f'Invalid positive integer: {val}')
def collatz(n):
# Relieved of printing, this function becomes simpler, more testable,
# and more general purpose.
while n > 1:
yield n
if n % 2 == 0:
n = n // 2
else:
n = 3 * n + 1
yield n
# Invoke main() if the program was executed rather than imported.
# This is important for testability, because testing tools need
# to import your code without executing the script in its entirety.
if __name__ == '__main__':
main(sys.argv[1:])
«Обзор кода» не означает написание программы, это означает, что пользователь вводит информацию о его программе. Как ваша программа должна помочь пользователю, написавшему свою первую программу на Python? Кроме того, ваша программа содержит много действительно плохих вещей, например, проверка ввода пользователя с помощью оператора assert.
— чудо173
@ miracle173 Я думаю, вы недооцениваете способность ОП многому научиться из этого ответа. И ваш комментарий подразумевает, что использование
assert
как инструмент для проверки «плохо» не имеет вообще никакой основы.— FMc