Python — цикл while внутри функции не дает согласованных результатов

#python #function #loops

#python #функция #циклы

Вопрос:

Новое в кодировании здесь. Я создал простую программу для класса, которая позволяет пользователю получать стоимость доставки пакета с плоской ставкой. Целью было включить функции в программу (функции в Python — это то подразделение, в котором мы находимся). Мой инструктор сказал, что моя программа работает так, как задумано, но я мог бы улучшить ее, используя цикл ‘while’, чтобы, если пользователь введет неправильный выбор, он не выбрасывал их из программы внезапно, а вместо этого снова запрашивал их для imput. Я использовал циклы ‘while’ раньше, но не внутри функции, и это приводило к запутанному результату.

Когда я запускаю программу сейчас, выход путем ввода ‘X’ останавливает программу, ЕСЛИ я сначала не перейду в подменю и не вернусь в главное меню. Также больше не отображается мое сообщение с благодарностью. Кроме того, если я захожу в подменю, возвращаюсь в главное меню и пытаюсь выйти, программа вместо этого отправляет меня в подменю. Наконец, использование цикла ‘while’ не приводит к ожидаемому результату, который должен позволить пользователю ввести ошибку ввода без сбоев. Любая помощь приветствуется! Надеюсь, мой вопрос имеет смысл.

 def main():
    # Create the menu text
    print('==================================')
    print('Box and Go')
    print('==================================n')
    print('C: Calculate cost to ship a package')
    print('D: Display shipping cost information')
    print('X: Exit Applicationn')
    # Allow the user to select a menu option
    selection = str(input('Enter your menu selection: ').upper())
    while selection.upper() != "X":
        if selection == 'C':
            CalculateCost()
        elif selection == 'D':
            DisplayInfo()
        elif selection == 'X':
            print('nThanks for choosing Box and Go!')


# Declare the function that shows the shipping rates
def DisplayInfo():
    print('==================================')
    print('SHIPPING COST INFORMATION')
    print('==================================n')
    print('All packages are flat rate shippingn')
    print('Flat Rate Envelopet $6.70')
    print('Small Flat Rate Boxt $7.20')
    print('Medium Flat Rate Boxt $13.65')
    print('Large Flat Rate Boxt $18.90n')

    # Allow the user to return to the main menu
    selection = str(input('Press enter to return to main menu: ').upper())

    if selection == '':
        main()

# Declare the function that will allow the user to
# find out the total price of each shipping option with tax included
def CalculateCost():
    print('==================================')
    print('COST ESTIMATOR FOR PACKAGES')
    print('==================================n')

    # The user will select their option here
    selection = str(input('Enter type of package to send:n(E)nvelope, (S)mall box, (M)edium Box, (L)arge box: ').upper())

    if selection == 'E':
        subtotal = 6.70
    elif selection == 'S':
        subtotal = 7.20
    elif selection == 'M':
        subtotal = 13.65
    elif selection == 'L':
        subtotal = 18.90
    # The program will call the CalcTax function to get the tax, then add that amount
    # to the subtotal, giving them the grand total cost of shipping
    print('nTotal Shipment Cost: $', format(CalcTax(subtotal)   subtotal, '.2f'), sep=''
          )
    # Allow the user to get back to the main menu(main function)
    main_menu = str(input('nPress enter to return to main menu'))

    if main_menu == '':
            main()


# Declare the function that will calculate
# tax based on the shipping selection the user made,
# then pass that amount back to the CalculateCost function
# that called it
def CalcTax(number):
    subtotal = number * 0.06
    return subtotal

# Call the main function. The program executes from here
main()
  

Ответ №1:

Вам не нужно

 main_menu = str(input('nPress enter to return to main menu'))
if main_menu == '':
    main()
  

Ваша функция должна просто передавать выполнение main() автоматически, но если вы хотите поместить туда что-то, чтобы сделать это явным, вы можете поместить return здесь.

Вариант 1:

 # Allow the user to get back to the main menu(main function)
str(input('nPress enter to return to main menu'))
# program will automatically go back to Main()
  

Вариант 2:

 # Allow the user to get back to the main menu(main function)
str(input('nPress enter to return to main menu'))
return # explicitly say to end this call to your function
  

Обновить:

Вы также не запрашиваете у пользователя ввод каждый раз, а получаете его один раз перед выполнением цикла. Вот ваш код с парой изменений:

 def main():
    while True:  # loop forever
        # Create the menu text
        print('==================================')
        print('Box and Go')
        print('==================================n')
        print('C: Calculate cost to ship a package')
        print('D: Display shipping cost information')
        print('X: Exit Applicationn')
        # Allow the user to select a menu option
        selection = str(input('Enter your menu selection: ').upper())
        if selection == 'C':
            CalculateCost()
        elif selection == 'D':
            DisplayInfo()
        elif selection == 'X':
            print('nThanks for choosing Box and Go!')
            break # end our forever loop


# Declare the function that shows the shipping rates
def DisplayInfo():
    print('==================================')
    print('SHIPPING COST INFORMATION')
    print('==================================n')
    print('All packages are flat rate shippingn')
    print('Flat Rate Envelopet $6.70')
    print('Small Flat Rate Boxt $7.20')
    print('Medium Flat Rate Boxt $13.65')
    print('Large Flat Rate Boxt $18.90n')

    # Allow the user to return to the main menu
    input('Press enter to return to main menu: ')


# Declare the function that will allow the user to
# find out the total price of each shipping option with tax included
def CalculateCost():
    print('==================================')
    print('COST ESTIMATOR FOR PACKAGES')
    print('==================================n')

    # The user will select their option here
    selection = str(input('Enter type of package to send:n(E)nvelope, (S)mall box, (M)edium Box, (L)arge box: ').upper())

    if selection == 'E':
        subtotal = 6.70
    elif selection == 'S':
        subtotal = 7.20
    elif selection == 'M':
        subtotal = 13.65
    elif selection == 'L':
        subtotal = 18.90
    # The program will call the CalcTax function to get the tax, then add that amount
    # to the subtotal, giving them the grand total cost of shipping
    print('nTotal Shipment Cost: $', format(CalcTax(subtotal)   subtotal, '.2f'), sep='')
    # Allow the user to get back to the main menu(main function)
    input('nPress enter to return to main menu')
    return


# Declare the function that will calculate
# tax based on the shipping selection the user made,
# then pass that amount back to the CalculateCost function
# that called it
def CalcTax(number):
    subtotal = number * 0.06
    return subtotal

# Call the main function. The program executes from here
main()
  

Комментарии:

1. Спасибо за ответ! Я попробовал оба варианта. К сожалению, они оба привели к невозможности выхода из функции «displayInfo». Я не смог вернуться в главное меню. Я также попробовал приведенные выше предложения «return str(input (‘Нажмите enter, чтобы вернуться в главное меню: ‘).upper()) «, которые привели к тому же результату. РЕДАКТИРОВАТЬ: я вижу ваше обновление. Я попробую. Я раньше не пробовал использовать «while true»

2. @tromegatron a while True: просто сообщает ему, что цикл продолжается вечно, и единственный способ выйти — это break ваш цикл.

3. Обновление 2: это сделало свое дело! Итак ….. программа не закрывалась, потому что я вызывал функцию снова и снова? Итак, каждый раз, когда я вызывал функцию, мне приходилось вводить ‘X’ в главном меню для каждой итерации функции, которая была … ‘открыта’, я думаю. Причина, по которой мне пришлось использовать ‘return’ в функции CalculateCost, заключалась в том, что ‘return’ закрывает итерацию функции, которую я вызвал, и возвращает пользователя обратно к функции, которая ее вызвала. Тогда, я предполагаю, что мне не нужен «return» в функции «displayInfo», потому что в ней нет значений, которые можно было бы вернуть?

4. @tromegatron Вы можете использовать return , даже если ваша функция не возвращает значение. В этом нет необходимости, но если это поможет вам подумать о том, как вы хотите «вернуть» выполнение вашей программы в основную функцию, это ничему не повредит, если поместить это туда. Основная проблема, которую я видел в вашем скрипте, заключалась в том, что selection = str(input('Enter your menu selection: ').upper()) он находился вне вашего цикла. Итак, ваше решение состояло в том, чтобы продолжать вызывать эту функцию, чтобы отобразить ее, но это приводило к вложенным while циклам при каждом вызове.

Ответ №2:

Это отличная возможность начать больше изучать область видимости переменной! По сути, selection не является глобальной переменной, и когда вы устанавливаете ее значение внутри DisplayInfo() , это значение фактически не передается обратно в main () . Вместо этого рассматриваю возможность использования return для отправки пользовательского ввода обратно в функцию.

Вот ваш код с парой изменений, исправляющих бесконечный цикл:

 ...
    while selection.upper() != "X":
        if selection == 'C':
             CalculateCost()
        elif selection == 'D':
            selection = DisplayInfo()
        elif selection == 'X':
            print('nThanks for choosing Box and Go!')


# Declare the function that shows the shipping rates
def DisplayInfo():
    print('==================================')
    print('SHIPPING COST INFORMATION')
    print('==================================n')
    print('All packages are flat rate shippingn')
    print('Flat Rate Envelopet $6.70')
    print('Small Flat Rate Boxt $7.20')
    print('Medium Flat Rate Boxt $13.65')
    print('Large Flat Rate Boxt $18.90n')

    # Allow the user to return to the main menu
    return str(input('Press enter to return to main menu: ').upper())
  

Я бы также рекомендовал потратить некоторое время на знакомство со стеком вызовов (т. Е. глубиной функций, вызываемых в программе). Когда вы вызываете main() внутри DisplayInfo() , вы фактически снова запускаете функцию с помощью рекурсии, потому что она уже выполняется вне этого контекста. Хотя предел стека (так сказать, пресловутое «переполнение») довольно высок, теоретически пользователь, который продолжает вводить ‘D’, в конечном итоге приведет к выходу вашей программы с ошибкой.