Python 数据模型文档 : an unbound user-defined method object and a class method object

标签 python oop object methods python-datamodel

在引用资料的Data Model中,作者花了很多精力解释User-defined methods是如何创建和操作的:(参见http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy并向下滚动)

User-defined method objects may be created when getting an attribute of a class (perhaps via an in- stance of that class), if that attribute is a user-defined function object, an unbound user-defined method object, or a class method object. 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.

未绑定(bind)的用户定义方法对象类方法对象有什么区别?

最佳答案

从“用户”的角度来看,Python 中的类方法是一种接收其类作为其第一个参数的方法 - 不同于接收类实例作为其第一个参数的“普通”方法 - 按照惯例是称为 self

如果你从一个类中检索一个“普通”方法,而不是从那个类的实例中检索,你会得到一个“未绑定(bind)方法”——即一个对象,它是一个函数的包装器,但它不会自动添加任何一个类本身,也不是任何实例作为调用时的第一个参数。因此,如果您要调用“未绑定(bind)方法”,您必须手动传递其类的实例作为其第一个参数。

如果你手动调用一个类的方法,另一方面,这个类被填入作为你的第一个参数:

>>> class A(object):
...   def b(self):
...      pass
...   @classmethod
...   def c(cls):
...      pass
... 
>>> A.b
<unbound method A.b>
>>> A.c
<bound method type.c of <class '__main__.A'>>
>>> A.c()
>>> A.b()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method b() must be called with A instance as first argument (got nothing instead)
>>> 

在幕后发生的事情或多或少是这样的——“新样式类”:

当定义一个类体时,方法只是普通函数——当类体结束时,Python 调用类的元类(通常是内置的 type )——并传递给它作为参数名称、基类和类主体字典。这个调用产生一个类——在 Python 中是一个对象,它是一个类,因为一切都是对象。

现在,Python 有一些自定义属性访问的巧妙方法 - 所谓的“描述符”。描述符是定义名为 __get__(或 __set____del__ 但我们在这里不关心这些)的任何对象。当访问 Python 中的类或对象的属性时,返回该属性引用的对象 - 除非它是类属性,并且对象是描述符。在这种情况下,Python 不会返回对象本身,而是对该对象调用 __get__ 方法,并返回其结果。例如,内置的 property 只是一个实现了 __set____get____del__ 的类.

现在,检索属性时发生的事情是,其主体上的任何函数(或类方法或未绑定(bind)方法,如数据模型所述)确实具有 __get__ 方法,这使得它是一个描述符。基本上,一个描述符在每次访问属性时检索命名为函数的对象,因为它在函数体上定义,围绕该函数创建一个新对象 - 一个在调用时将自动填充第一个参数的对象 - 这是也就是说,一个方法

例如:

>>> class B(object):
...    def c(self):
...      pass
...    print c
... 
<function c at 0x1927398>
>>> print B.c
<unbound method B.c>
>>> b = B()
>>> b.c
<bound method B.c of <__main__.B object at 0x1930a10>

如果你想检索函数对象,而不转换为方法对象,你可以通过类的__dict__属性来实现,它不会触发描述符:

>>> B.__dict__["c"]
<function c at 0x1927398>
>>> B.__dict__["c"].__get__
<method-wrapper '__get__' of function object at 0x1927398>
>>> B.__dict__["c"].__get__(b, B)
<bound method B.c of <__main__.B object at 0x1930a10>>
>>> B.__dict__["c"].__get__(None, B)
<unbound method B.c>

至于“类方法”,这些只是不同类型的对象,用内置的 classmethod 显式修饰 - 当它的 __get__ 被调用时它返回的对象是原始函数的包装器,它将填充 cls 作为调用时的第一个参数。

关于Python 数据模型文档 : an unbound user-defined method object and a class method object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9090941/

相关文章:

c# - 静态类 VS 私有(private)构造函数

python - a 是什么意思? Python 中的 import 语句是什么意思?

python - 批量加载和处理图像的最pythonic方式

python - PyQt - 更新模型时自动刷新自定义 View ?

python - 在 Python 中播放和控制 mp3 文件?

java - minStack 子类使用一个对象作为最小堆栈和常规堆栈

javascript - AJAX请求导致 'undefined is not an object'错误

php - 在 PHP 中我的类的任何方法之前调用特殊方法

oop - 什么时候类(class)太大?

javascript - 如何访问 module.exports 中的对象属性