【问题标题】:User-defined methods and the __func__ attribute用户定义的方法和 __func__ 属性
【发布时间】:2014-11-06 12:15:55
【问题描述】:

有人能解释一下Python datamodel reference 中关于用户定义函数的以下部分是关于什么的吗?

当通过检索另一个用户定义的方法对象创建时 来自类或实例的方法对象,其行为与 对于函数对象,除了 new 的 __func__ 属性 instance 不是原始方法对象,而是它的__func__ 属性。

我尝试使用以下方法进行测试:

class A(object):
    def foo(self):
        print 'done'
    bar = foo
class B(object): pass

a = A()
b = B()
b.f = a.foo
b.f.__func__  #output:- <function foo at 0x7fe55bed4230>
a.foo.__func__ #output:- <function foo at 0x7fe55bed4230>

两个语句都给了我相同的输出,但 b.f.__func__ 没有给我原来的 方法对象。我理解正确吗?

【问题讨论】:

    标签: python python-2.7


    【解决方案1】:

    文本描述了绑定行为;如果一个方法已经被绑定,但是你通过descriptor protocol检索它,那么一个方法对象就像一个函数对象,但是__func__属性被重用,而不是让新方法对象指向旧方法对象。

    您可以通过访问foo 作为类或实例的属性来触发描述符协议:

    >>> class A(object):
    ...     def foo(self):
    ...         print 'done'
    ... 
    >>> a = A()
    >>> a.foo
    <bound method A.foo of <__main__.A object at 0x1007611d0>>
    >>> A.foo
    <unbound method A.foo>
    >>> A.__dict__['foo']
    <function foo at 0x10075cc08>
    >>> A.bar = A.foo
    >>> A.bar
    <unbound method A.foo>
    >>> A.__dict__['bar']
    <unbound method A.foo>
    >>> a.bar
    <bound method A.foo of <__main__.A object at 0x1007611d0>>
    >>> a.bar.__func__
    <function foo at 0x10075cc08>
    

    在上述会话中,我使用A.__dict__ 绕过描述符协议。可以看到A.__dict__['foo']是一个函数对象,而A.__dict__['bar']是一个未绑定的方法。然而,当您访问A.bara.bar 时,您会得到一个指向原始函数对象的方法对象,而不是我们从A.foo 检索到的方法。

    所以你的理解似乎是正确的; b.f 是(绑定的)a.foo 方法,因此 b.f.__func__ 将导致与 a.foo.__func__ 相同的对象。

    【讨论】:

    • 这是python 2.7吗?我在另一篇文章中读到,当调用A.foo 时,python 3.x 将返回一个函数。我是不是弄错了?
    • @Dzhao:是的,这是 Python 2.7;在 Python 3.x 中 A.foo 返回函数对象不变。
    • 什么是'属性被重用而不是让新方法对象指向旧方法'是什么意思?
    • @henryren:描述符协议在函数或方法对象上调用__get__function.__get__() 返回一个方法对象,其__func__ 属性指向原始函数。调用method.__get__ 会返回一个新方法对象,其__func__ 属性也指向相同的原始函数对象,而不是您调用__get__ 的方法对象。有些人可能期望 __func__ 属性指向方法对象,而不是创建一个链。
    • @panda-34:我已经向clean out those vestiges提交了一个拉取请求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多