为什么字典中传递参数的函数会立即执行?

问题描述 投票:0回答:2

我对 Python 还很陌生。

我正在创建一个执行一系列功能的脚本。

我不知道我会执行多少功能,所以我选择了一个菜单,其中的选项基于全局字典,其中的键代表用户的输入选择和调用相关函数的值。

如下面的代码片段所示,在字典中,有几个

func2
函数。

最初我单独处理这些函数(

func2
func3
func4
,...)。但我注意到这些都遵循共同的基本模式重复出现。因此,由于我最近介绍了 OOP 中的类,我想我可以将这些函数抽象为一个类。

这个想法是将每个

choices
键与一个函数相关联,在
func2
的情况下,我将向该函数传递“标识符”参数。

这些参数已被定义为另一个嵌套字典

dict
)中的键。因此,在调用类构造函数并创建通用对象之后,通过类别,我会将单个嵌套字典
dict:{"CatA" : {sub_dict}, ... }
)传递给该对象的方法,该方法将产生总计,并且这将与它所属的类别。

#main.py
from menu import *

choises = {
 "1": func1,
 "2": func2("CategoryA"),
 "3": func2("CategoryB"),
 ...
 "7": func3,
 ...
}

def main():
 while True:
  printMenu()  # the print lines are set up like this: `num) description`
  choice = input("Enter choice: ")

  if choice == "0":
   break
  elif choice in choices:
   choices[choice]()
  else:
   print("Invalid Choice")

if __name__ == "__main__":
 main()
# menu.py
def func1():
 ...

def func2(category: str):
 from dict import extractDict
 from classfunc2 import ClassFunc2

 dict = extractDict()
 obj = ClassFunc2()
 total = obj.totNumber(**dict[category])
 obj.printResults(total,category)

def func3()
 ... 
 
def printMenu()
 ...
# classfunc2.py
class ClassFunc2:
 def __int__(self):
  return

 totNumber(self, **dict):
  ...
  a = input(smth)
  ...
  return total

 printResults(self, total, category):
  print()

但是问题来了: 当我运行脚本时,由于某种我不知道的原因,在我从菜单中选择它们之前,only所有

func2
实例都会被执行。 我非常确定我在抽象上做错了,但我根本不知道哪里错了。

有人可以向我解释为什么会发生这种情况以及我应该如何修复这个脚本吗?

PS:我知道标题不准确,但我不知道还能写什么。如果您能分享一些关于如何改进标题的想法,我将不胜感激。

python function oop
2个回答
0
投票
choises = {
 "1": func1,
 "2": func2("CategoryA"),
 "3": func2("CategoryB"),
 ...
 "7": func3,
 ...
}

您看到字典使用

func2
func1
func3
的主要区别了吗?

func2
的引用在函数名后也有括号
()
,表示该函数被调用立即,并且返回值存储在字典中。

但是

func1
func3
后面没有括号,所以字典存储的是实际的函数对象,称为later

如果您希望

func2
稍后被称为 ,例如
func1
func3
,请去掉字典定义中的括号。

编辑:

如果您希望字典也包含函数调用的参数,有多种方法可以实现。这是一种方法:

choises = {
 "1": [func1],
 "2": [func2, "CategoryA"],
 "3": [func2, "CategoryB"],
 ...
 "7": [func3],
 ...
}

字典值是列表,其中第一个值是函数对象本身,其他值(如果有)是要传递给函数的参数。


0
投票

问题是您在定义字典时立即调用函数,然后将这些函数的返回值保存在字典中。假设您的 function1 返回 None 。这意味着,您的函数首先被执行,然后值 None 将保存在您的字典中,而不是函数本身,因为您是用括号调用它的。

错误:

func2("my argument")

您不想传递函数的输出,而是传递函数本身。因此,您需要创建一个函数来使用所需的参数调用您的函数。

一个简单但冗长的解决方案如下所示:

def call_func_2():
    func_2("my argument")

menu_dictionary = {"2": call_func_2}

请注意,前面的示例在初始化字典时并未调用该函数。

更好的方法是使用 lambda 函数。这些是小型单行函数,允许您包装函数调用,而无需在字典之外定义其他函数。在我看来,这是最干净的方法,并以最有效的方式解决您的问题:

menu = {
    "1": func_1,
    "2": lambda: func_2("my param"),
    "3": lambda: func_3([1, 2, 3], "param")
}

请注意,如果您不想向函数传递参数,则无需将函数调用包装在 (lambda) 函数中。

© www.soinside.com 2019 - 2024. All rights reserved.