我想将此函数绑定为某个类的方法:
def foo_method(msg, self):
print self.prefix + msg
这有效:
class A(object):
prefix = 'msg: '
A.foo = lambda *args: foo_method('hello', *args)
A().foo()
# => msg: hello
然而,这不是:
from functools import partial
class B(object):
prefix = 'msg: '
B.foo = partial(foo_method, 'hello')
B().foo()
# => TypeError: foo_method() takes exactly 2 arguments (1 given)
第一个例子似乎被正确绑定,而第二个例子没有。
为什么?
答案 0 :(得分:1)
答案是:描述符!自绑定仅在属性访问期间发生。方法没有特殊的语言支持 - 它们只使用函数对象和描述符。
引用https://docs.python.org/2/howto/descriptor.html#functions-and-methods:
类字典将方法存储为函数。 [...]为了支持方法调用,函数包括__get __()方法,用于在属性访问期间绑定方法。这意味着所有函数都是非数据描述符,它们返回绑定或未绑定方法,具体取决于它们是从对象还是类调用。在纯python中,它的工作方式如下:
class Function(object): def __get__(self, obj, objtype=None): "Simulate func_descr_get() in Objects/funcobject.c" return types.MethodType(self, obj, objtype)
魅力!
访问A().foo
时,调用描述符机制,调用foo_method.__get__
,返回绑定方法:
A().foo
# => <bound method A.<lambda> of <__main__.A object at 0x10ca9c0d0>>
由于functools.partial
未实现__get__
,因此不受约束:
B().foo
# => <functools.partial at 0x10caf3aa0>
hasattr(partial(foo_method, 'hello'), '__get__')
# => False
问题仍然存在:如果它如此简单,为什么没有 functools.partial也会实现这一点?