getattr出错

1 投票
2 回答
1916 浏览
提问于 2025-04-17 00:20

我本来想去看一个关于如何在Python中通过字符串调用模块函数的问题,但每当我在程序中调用我的类时,就会出现这个错误:TypeError: unbound method bar() must be called with foo instance as first argument (got nothing instead)。

有人能帮我解决这个问题吗?

2 个回答

1

我们来看这个例子:

class Foo:
  def bar(self):
    print 'bar'
  @classmethod
  def baz(cls):
    print 'baz'
  @staticmethod
  def qux():
    print 'qux'

def quux():
  print 'quux'
Foo.quux = quux  # note: Foo.quux is a function attribute NOT a method

然后你可以根据调用这些方法的方式,得到不同的成功标准:

f = Foo()
f.bar()  # works
getattr(f, 'bar')()  # works
getattr(Foo, 'bar')()  # TypeError
getattr(Foo, 'bar')(f)  # works
f.baz()  # works
getattr(f, 'baz')()  # works
getattr(Foo, 'baz')()  # works

等等。这里的基本概念是,当你调用一个方法时,使用的语法是 obj.method(...),这个对象本身会作为第一个 self 参数传递;但是当你把同样的方法当作类的一个属性来使用时,这个特殊的替换就不会发生。这一点在 getattr 函数中也是适用的。

9

这里有一个典型的情况,会导致你所描述的问题。

class Foo(object):
    def bar(self,x):
        print(x)

foo=Foo()

调用 getattr(Foo, 'bar') 会返回未绑定的方法 Foo.bar

getattr(Foo,'bar')(1)

结果是

类型错误:未绑定的方法 bar() 必须以 Foo 实例作为第一个参数调用(而不是 int 实例)

这个方法 Foo.bar 被称为“未绑定”,因为在调用时没有提供实例(比如 foo)作为第一个参数。毕竟,如果只提供了类 Foo,怎么能有实例呢?

另一方面,如果你提供了这个类的实例:

getattr(foo,'bar')(1)

结果是

1

因为 foo.bar 是一个“绑定”的方法——当调用 foo.bar 时,foo 会作为第一个参数提供。

附注:你的错误信息中提到,“...用 foo 实例调用...”。与我上面提到的错误信息相比,看来你的类名是小写的 foo。请注意,PEP8 风格指南 建议类名总是用大写字母,而实例名用小写字母。这样做可以帮助你避免这个错误。

撰写回答