программа двоичного / шестнадцатеричного преобразования командной строки на Python

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

while True:
    while True:
        conv_type = input("Hexadecimal or Binary?: ").lower()
        if "b" not in conv_type and "h" not in conv_type:
            print("Invalid Input")
            continue
        else:
            break

    while True:
        try:
            dec_num = int(input("Decimal Number: "))
        except ValueError:
            print("Invalid Input")
            continue
        break

    if "h" in conv_type:
        print("   ", dec_num, "=", hex(dec_num), "in hexadecimal")

    if "b" in conv_type:
        print("   ", dec_num, "=", bin(dec_num).replace("0b", ""), "in binary")

Как бы вы это улучшили? Я чувствую себя немного странно, используя три while True циклы в той же программе, но я не мог придумать лучшего решения на лету. Любые отзывы приветствуются!

1 ответ
1

Проверка ввода пользователя раздражает, правда? Мой инстинкт — задавать меньше вопросов. Действительно ли пользователю нужно запрашивать шестнадцатеричный или двоичный код? Например, мы могли бы просто распечатать оба преобразования. А если это сценарий командной строки, не может ли десятичное число поступать непосредственно из командной строки? Или даже набор десятичных чисел, и наш скрипт может их все преобразовать.

Но если мы сохраним ваш текущий подход, повторяемость проверки предполагает необходимость переноса кода в функции и создания единой функции для обработки всех input() звонки. Как минимум, для этой функции требуется приглашение пользователя и функция (или вызываемая), которая преобразует значение и выдает ошибку, если оно недействительно. Например, чтобы проверить тип преобразования, нам нужно ввести ввод в нижний регистр, а затем убедиться, что он содержит b или же h. Пока мы занимаемся этим, мы могли бы упростить последующую логику, определив константы для conv_type. Последующий код может использовать строгое равенство для управления логикой (а не более свободный in чеки). И в этом случае константа также может служить меткой при печати.

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

Если вы снимете 0b префикс для двоичного кода, разве вы не должны сделать то же самое для шестнадцатеричного? Если да, то это упрощает логику, потому что мы можем извлекать вещи, которые различаются, в структуру данных (converters), а затем использовать эту структуру для управления логикой. В результате большая часть «алгоритма» в main() функция исчезает, и мы получаем очень небольшое условное ветвление. Вместо этого он просто идет шаг за шагом, вызывая служебные функции или напрямую обращаясь к структурам данных. Вместо этого алгоритмическая сложность делегируется меньшим и более узконаправленным вспомогательным функциям, о которых легче думать изолированно.

import sys

HEX = 'hexadecimal'
BIN = 'binary'

def main(args):
    # Set up conversion functions and prefixes.
    converters = {
        HEX: (hex, '0x'),
        BIN: (bin, '0b'),
    }

    # Perform conversions.
    while True:
        # Get validated input. Since int() will raise if given
        # a bad input, we get that validation for free.
        conv_type = get_user_input('Hexadecimal or binary', is_conv_type)
        dec_num = get_user_input('Decimal number', int)

        # Convert.
        func, prefix = converters[conv_type]
        converted = func(dec_num).replace(prefix, '')

        # Report.
        print(f'    {converted} = in {conv_type}')

def get_user_input(prompt, validate):
    while True:
        # Get input and provide a way for user to quit easily.
        reply = input(prompt + ': ').lower().strip()
        if not reply:
            sys.exit()

        # Return valid converted input or nag the user.
        try:
            return validate(reply)
        except ValueError as e:
            print(f'Invalid input: {reply}')

def is_conv_type(reply):
    # Takes user input. Returns HEX or BIN if valid.
    reply = reply.lower()
    for conv_type in (HEX, BIN):
        if conv_type[0] in reply:
            return conv_type
    raise ValueError()

if __name__ == '__main__':
    main(sys.argv[1:])

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

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