本问题已经有最佳答案,请猛点这里访问。
Possible Duplicate:
Calling a function from a string with the function's name in Python
我想我可以写一些糟糕的代码来实现这一点,但是我更愿意看到"干净的版本"。
在我看来,最好的方法是创建一个dict,它包含给定对象可以使用的各种函数。然后,当用户被指示告诉对象它在做什么时,它会根据该dict吐出一个菜单。
我到处找了一下,并没有真正发现适合我的东西,所以我想我应该试一试。但它没有成功。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29class Man(object):
def __init__(self):
self.cmds = ['foo', 'bar']
def foo(self):
print"Foo called."
def bar(self):
print"Bar called."
def junk(self):
print"Junk called." ##not in dict, on purpose, will explain
def menu(self):
while True:
print"List of actions:"
for acts in self.cmds:
print acts
cmd = raw_input(">")
if cmd in self.cmds:
cmd() ##doesn't work.
##neither did self.cmd() (got AttributeError, obviously)
result = getattr(self, cmd)() ## this works! thanks cdhowie
else:
pass
Stick = Man()
Stick.menu()
如果不明显的话,每当我输入if-else认为正确的东西时,程序就会给出类型错误——在本例中,输入"foo"或"bar"。事情是这样的,我知道我可以在这里写一个又长又丑的if-else来让这个例子工作,但是我想能够从self中添加/删除。更改对象的功能。因此,第三个函数Junk();Stick不能从当前的dict-menu中访问"Junk()",但可以使用一个小小的self.cmds。追加动作,我希望它能够。
该死的蟒蛇,它们是怎么工作的?这是正确的方法,还是有更简单的方法?
编辑:我的答案是在getattr的魔力中找到的。谢谢cdhowie。诀窍是将while循环更改为:result = getattr(self, cmd)()
现在我知道我的下一个任务是最终弄清楚getattr()实际上做了什么。请原谅我的新手身份,呵呵,我不知道我在写什么:)
最后编辑:虽然cdhowie的示例与原始程序兼容,但我发现ders的答案允许我在功能上做一些getattr()无法做到的事情;ders的解决方案让我更容易在其他对象中使用函数在Man的init中,我想这叫做对象合成,对吧?无论如何,getattr()都会将任何添加到self的函数归为AttributeError。除了人类,其他地方都有cmds。或者我又做了一件奇怪的事。但只要说,德斯FTW。
如果您想按名称调用方法,这个问题是相关的。
哦,这招很管用。快速而简单的回答,谢谢薄荷糖。
您是否通过代码更新来编辑您的问题以解决您的问题?如果是,则需要删除或关闭此Q。
是的,我同意。由于我是一个新用户,显然我不能为别人回答我自己的问题。7个小时。是的。
以你为例。cmds是一个列表,而不是字典。当self中的字符串时,它们会引发TypeError。将cmds列表作为函数调用。
创建一个字典,将函数名作为字符串与函数本身配对。
1
2def __init__(self):
self.cmds = {'foo':self.foo, 'bar':self.bar}
在菜单函数中,检查用户是否输入了有效的函数名。如果是这样,就从字典中找出它并调用它。
1
2
3
4
5if cmd in self.cmds:
command = self.cmds[cmd]
command()
else:
pass
要动态添加junk函数,可以使用update cmds:
1Stick.cmds.update({'junk':Stick.junk})
事实上,这个答案让我找到了我需要的答案。太棒了。谢谢。
不要使用update向Stick.cmds添加单个项目,只需使用Stick.cmds['junk'] = Stick.junk。