【问题标题】:How to bind partial function as method on Python class instances如何将部分函数绑定为 Python 类实例的方法
【发布时间】:2018-06-28 11:25:07
【问题描述】:

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

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)

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

为什么?

【问题讨论】:

  • 有趣。现在调查这个。我希望这只是您正在玩的一个实验,您实际上并没有尝试将部分应用的方法动态添加到类中。
  • 这里不需要setattrA.foo = lambda # ... 也表现出这种行为。
  • 我敢说这是一些奇怪的交互,因为 lambda 是一个适当的函数,而 partial 是一个 Callable(它实际上是作为一个类实现的)。
  • @BaileyParker 是的,我猜这与 partial 不是函数有关,我只是无法找到解释为什么这很重要。也许是我不理解的对象模型中的某些东西?
  • 所以它位于__getattribute__ 的自绑定中。 A().foo 产生 <bound method <lambda> of ...>>B().foo 产生 functools.partial(<function foo_method at ...>, 'hello')。所以看起来B __getattribute__ 不会自绑定。要获得答案,您必须深入研究元类的世界。

标签: python python-2.7 oop functional-programming


【解决方案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 也实现这个?

【讨论】:

    猜你喜欢
    • 2013-04-02
    • 2012-02-17
    • 2013-11-25
    • 2020-07-17
    • 2021-04-24
    • 2016-11-30
    • 1970-01-01
    • 2011-06-08
    • 2016-05-21
    相关资源
    最近更新 更多