如何将部分函数绑定为Python类实例上的方法

时间:2018-01-19 09:01:27

标签: python python-2.7 oop functional-programming

我想将此函数绑定为某个类的方法:

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)

第一个例子似乎被正确绑定,而第二个例子没有。

为什么?

1 个答案:

答案 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也会实现这一点?

相关问题