从类中调用函数字典
我刚接触Python,想创建一个类,这个类里面有一个字典,用来对应类中的不同方法。目前我有:
class Test:
functions = {"Test1":test1, "Test2":test2}
def test1(self, arg1):
print "test1"
def test2(self, arg1):
print "test2" + arg1
def call_me(self, arg):
self.functions[arg](arg)
然后在我的main.py文件中,我有以下内容:
from Test import Test
t = Test()
t.call_me('Test1')
当我调用这个函数时,出现了一个错误,提示说test1这个名字没有定义。有没有人能告诉我我哪里出错了?非常感谢任何帮助。
3 个回答
在你的字典里,"Test1"
和 "Test2"
是大写的,而对应的函数名却是小写的。把字典里的键改成小写,应该就能正常工作了。
你需要在你的参数周围加上字符串引号,而且“T”要大写:
t.call_me('Test1')
不过,Python其实已经内置了你想要实现的功能,可以通过getattr
这个方法来使用。也就是说,你可以直接这样做:
def call_me(self, arg):
return getattr(self, arg)()
注意,在这种情况下,名字必须和方法名完全一致,否则会出现AttributeError
错误,所以应该是:
t.call_me('test1')
更新
现在你已经修改了你的问题,问题就变得清楚了:
class Test:
functions = {"Test1":test1, "Test2":test2}
这是在静态/类作用域下定义functions
。此时,test1
和test2
实际上还没有被创建,它们也没有和类实例绑定(所以不知道self
应该是什么)。如果你想要有任意的映射(这样getattr
就不适用了),正确的做法是把这个放到__init__()
里面:
class Test:
def __init__(self):
self._functions = {"Test1":self.test1, "Test2":self.test2}
def call_me(self, arg):
return self._functions[arg](arg)
你这里有几个问题。
首先,在这一行:
functions = {"Test1":test1, "Test2":test2}
当Python执行这行代码时,test1
和test2
这两个东西根本不存在,所以你会立刻遇到NameError
错误。如果你想这样做,你需要在定义所有函数之后再去调用它们,而不是在之前。
接下来,在同一行中,test1
和test2
此时只是普通的函数。但你却试图把它们当作方法来调用,使用了魔法般的self
等等。这是行不通的。如果你理解方法是怎么工作的,你应该能明白在call_me
方法中可以绕过这个问题:
def call_me(self, arg): self.functions[arg].__get__(self, type(self))(arg)
(在这种情况下,你也可以直接把self
作为额外的参数传递过去。但在这样做之前,确保你理解原因。)
最后,你试图用函数test1
来调用call_me
,而不是用名字'Test1'
。你创建这个映射的原因大概就是为了能够使用这些名字(动态地,以字符串形式),所以我们实际上应该使用这些名字:
t.call_me('Test1')
注意,如果你不能使用getattr
的唯一原因是你想查找的运行时名字和你想定义的方法名字不一样,你可以始终创建一个字符串到字符串的映射,然后用getattr
查找结果字符串,这样就能避免这里的其他问题。借用aruisdante的回答,加入名字查找并记得传递arg
:
functions = {"Test1": "test1", "Test2": "test2"}
def call_me(self, arg):
return getattr(self, self.functions[arg])(arg)