python - 不确定 Python 文档中关于用户定义方法对象的说法

标签 python class methods

来自 Python 语言引用 Data Models section ,在用户定义的方法标题下:

When the attribute is a user-defined method object, a new method object is only created if the class from which it is being retrieved is the same as, or a derived class of, the class stored in the original method object; otherwise, the original method object is used as it is.

这句话是什么意思?

最佳答案

当您在类或实例上查找名称时,Python 2 会绑定(bind)函数,请参阅 descriptor protocol 。在类上执行此操作时,结果是未绑定(bind)方法:

>>> class Foo(object):
...     def bar(self):
...         return 'Method bound to {!r}, from class Foo'.format(self)
...     def __repr__(self):
...         return '<Instance of type {!r}>'.format(type(self))
...
>>> Foo.bar
<unbound method Foo.bar>

该对象仍然包含对原始类以及原始函数对象的引用:

>>> Foo.bar.im_class
<class '__main__.Foo'>
>>> Foo.bar.__func__  # new name, old name im_self still works too
<function bar at 0x105d2a9b0>

这里的术语未绑定(bind)指的是它没有绑定(bind)到实例;但是它绑定(bind)到类。

文本告诉您,当您将此类未绑定(bind)方法对象粘贴到另一个类上时,它将像对待函数一样对待它们。因此,如果这样做,方法对象将反弹到新类;原来的函数对象被引用并反弹到新的类:

>>> class Bar(Foo):
...     bar = Foo.bar   # an unbound method from the Foo class!
...
>>> Bar.bar
<unbound method Bar.bar>
>>> Bar.bar.im_class
<class '__main__.Bar'>
>>> Bar().bar()  # it'll work like any other method
"Method bound to <Instance of type <class '__main__.Bar'>>, from class Foo"

这里BarFoo的子类,未绑定(bind)的方法对象重新绑定(bind)到类Bar上。

但是,文本指出,如果将未绑定(bind)方法粘贴到不是 Foo 子类的其他类上,则不会完成此操作:

>>> class Baz(object):   # not derived from Foo
...     bar = Foo.bar
...
>>> Baz.bar
<unbound method Foo.bar>
>>> Baz.bar.im_class
<class '__main__.Foo'>
>>> Baz().bar
<unbound method Foo.bar>
>>> Baz().bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)

您必须通过 Foo.bar.__func__ 访问原始函数,或者通过访问类 __dict__ 来完全规避描述符协议(protocol)(因此使用 Foo.__class__['bar']) 来完全避免这个问题。

引用文档中的文本相当困惑,因为这并不适用于完全绑定(bind)的方法,尽管它暗示它应该适用;即使在类上使用,它们也永远不会重新绑定(bind):

>>> class Spam(object):
...     bar = Foo().bar  # *bound* method, taken from an instance of Foo
...
>>> Spam.bar
<bound method Foo.bar of <Instance of type <class '__main__.Foo'>>>
>>> Spam().bar
<bound method Foo.bar of <Instance of type <class '__main__.Foo'>>>
>>> Spam().bar()
"Method bound to <Instance of type <class '__main__.Foo'>>, from class Foo"

Python 3 完全摆脱了未绑定(bind)的方法;从类对象中检索函数会得到原始函数对象。上述限制已完全取消。

关于python - 不确定 Python 文档中关于用户定义方法对象的说法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36420410/

相关文章:

python - Pandas :对多列进行逐行操作

css - 空类定义陷阱?

java - 如何创建File类的实例?

ruby - 低效的 Ruby 方法命名 : passing namespace as argument as a way to call methods

java - 方法签名中的对象数组

python - 将两个二维数组组合成一个图像图

javascript - 通过scrapy python中的javascript与splash实现下一页?

c# - 组合方法

python - 如何矢量化 3D numpy 数组中切片的阈值

c++ - G++未定义对类::函数的引用