Почему вызывается эта функция (функция переключения python для пользовательского ввода)?

#python #python-3.x #dictionary #switch-statement #user-input

#python #python-3.x #словарь #switch-statement #пользовательский ввод

Вопрос:

Я новичок в python и пытаюсь настроить программу командной строки, которая запускает несколько разных команд на основе пользовательского ввода. Пользовательский ввод будет отправлен в функцию со словарем различных функций. Мой код пока выглядит так: `

Функции для различных параметров команды

 def quit():
   print("youre quiting")
   ender = False

def ls():
   print("You're listing files!")
  

Словарь, отображающий ввод в командные функции

  def commands(argument):
   switcher = {
      "quit": quit(),
      "ls": ls(),
      3: "you typed 3",
   }
   return switcher.get(argument, "Invalid command")
  

Основной командный цикл: принимает пользовательский ввод, проверяет, сколько аргументов введено, и вызывает соответствующую командную функцию

 while ender == True:

userIn = input("okay go:")
userSplit = userIn.split()
numArgs = len(userSplit)

if numArgs == 0:
    print("You must enter a command! Use the command 'help' for more information.")
elif numArgs >= 2:
    print("You entered too many arguments! Use the command 'help for more information.")
else:
    print(commands(userSplit[0])
  

Независимо от того, что я ввожу, он вызывает функции ls и quit и печатает их операторы. Однако, если я ввожу недопустимую команду, которая работает и сообщает мне, что она недействительна (в дополнение к вызову этих двух функций).

Что здесь происходит? Как я могу заставить его вызывать только ту функцию, которую я ввожу? Спасибо за ваше время.

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

1. Чтобы заполнить ваш switcher словарь, интерпретатор должен выполнить эти функции.

2. Они вызываются, потому что вы их вызываете. Просто не делайте этого.

3. Итак, как я мог бы вызывать их только после пользовательского ввода? Мне просто нужно использовать большой блок if else?

Ответ №1:

quit() , например. затем вызывает функцию и сохраняет результирующее значение в качестве значения словаря. Просто сохраните функцию, не вызывая ее сначала:

 switcher = {
  "quit": quit,
  "ls": ls,
  "3": lambda: print("You typed 3!")
}
fn = switcher[cmd]
fn() # now call the selected function
  

Сделайте все значения функциями / лямбдами для единообразия вызова и используйте строки для всех ключей, чтобы они были найдены.

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

1. Спасибо! Я действительно не понимал использование лямбды до этого, python начинает иметь для меня больше смысла.

2. Это решает проблему ваших функций — но ваша реализация «quit» не будет работать как есть, потому что переменная «ender» внутри вашего метода quit является локальной для функции — не изменит значение переменной «ender» в вашем исполнении.

Ответ №2:

Когда вы создаете словарь, который вы вызываете ls() вместо назначения ключа «ls» для ссылки def ls() на .

Поэтому при каждом вызове commands() создается словарь и вызываются оба quit() и ls() . Ваш словарь во время выполнения становится

 {
  "ls": None, 
  "quit": None,
}
  
 def test(argument):
    def ls():
        print("you're listing")

    def lsCorrect():
        print("you're listing from a function reference")

    switcher = {
        "ls": ls(),
        "lsCorrect": lsCorrect,
    }
    return switcher.get(argument, "default")


print('first call')
# switcher[lsCorrect] => reference to lsCorrect, so we then invoke it with ()
test("lsCorrect")()
try:
    print('second call')
    # when constructing the dictionary ls() is invoked and that function returns None
    # so we get a TypeError trying to call a function on None
    test("ls")()
except TypeError:
    print('tried to invoke something thats not a function')