Базовая программа Collatz с проверкой ввода в Python

В главе 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 ответ
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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *