Python 默认参数的函数
我该如何在方法里访问 qux
呢?我真的需要在 foo()
的内部重新定义它吗,还是有办法从 self
导入它?
class Baz(object):
qux = lambda x : x + '_quux'
def foo(self, bar=qux('fred')):
print bar
print qux('waldo')
# NameError: global name 'qux' is not defined
print Baz.qux('waldo')
# TypeError: unbound method <lambda>() must be called with Baz instance as first argument (got str instance instead)
print Baz.qux(self, 'waldo')
# TypeError: <lambda>() takes exactly 1 argument (2 given)
print self.qux('waldo')
# TypeError: <lambda>() takes exactly 1 argument (2 given)
3 个回答
1
一种解决办法是使用
qux = staticmethod(lambda x : x + '_quux')
然后这样访问它
Baz.qux('waldo')
我建议把它移出这个类。
7
如果你想从类中访问某个方法,那么你必须使用 classmethod
或 staticmethod
。
class Baz(object):
qux = staticmethod(lambda x : x + '_quux')
但是 不要这样做。
1
qux
被当作实例方法来处理,因为这是类成员看起来像函数时的默认处理方式(更具体地说,当你通过一个实例查找 Baz.qux
时,会隐式调用 __get__
来将第一个参数绑定到实例上)。但是,你没有在开头提供 self
参数。因此,baz
被绑定到了 x
这个 lambda 参数上。
在 Python 中,'self' 这个名字并没有什么神奇之处;它只是一个约定。 方法绑定总是通过绑定到函数的第一个参数来工作的。
如果你聪明的话,可以自己验证这一点:
class Baz(object):
qux = lambda x: x + '_quux'
def foo(self): return self.qux()
Baz().foo() # TypeError: unsupported operand type(s) for +: 'Baz' and 'str'
# because after binding Baz() to 'x', we get Baz() + '_quux'
一个解决方案是明确将 qux
设为 staticmethod
,就像 Sven Marnach 的回答中提到的那样。(你也可以将它设为 classmethod
,这是 Python 特有的概念,更加强大;staticmethod
的行为更接近于 Java 中的 static
关键字。)注意,和 Java 一样,你也可以在 foo
中通过 self.qux
来访问 staticmethod
。这通过用 staticmethod
安装的新机制替换了函数的正常 __get__
机制来实现。
另一个解决方案是在 lambda 参数中提供 self
参数。如果你实际上不想要“静态”行为(也就是说,确实需要做一些与 self
相关的事情)——但看起来你确实想要。为了完整性,这样写会是:
qux = lambda self, x: x + '_quux'
def foo(self):
return self.qux('foo')