从类中调用函数字典

5 投票
3 回答
9040 浏览
提问于 2025-04-30 17:38

我刚接触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 个回答

0

在你的字典里,"Test1""Test2" 是大写的,而对应的函数名却是小写的。把字典里的键改成小写,应该就能正常工作了。

7

你需要在你的参数周围加上字符串引号,而且“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。此时,test1test2实际上还没有被创建,它们也没有和类实例绑定(所以不知道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)
7

你这里有几个问题。

首先,在这一行:

functions = {"Test1":test1, "Test2":test2}

当Python执行这行代码时,test1test2这两个东西根本不存在,所以你会立刻遇到NameError错误。如果你想这样做,你需要在定义所有函数之后再去调用它们,而不是在之前。


接下来,在同一行中,test1test2此时只是普通的函数。但你却试图把它们当作方法来调用,使用了魔法般的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)

撰写回答