Python数据模型文档:未绑定的用户定义的方法对象和类方法对象
作者:互联网
在参考文献的数据模型中,作者花了很多精力来解释如何创建和操作用户定义的方法:(见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.
那么未绑定的用户定义的方法对象和类方法对象之间的区别是什么?
解决方法:
从“用户”的角度来看,Python中的类方法是一个接收其类作为其第一个参数的方法 – 与接收类的实例作为其第一个参数的“普通”方法不同 – 按照惯例,它被称为self.
如果从类中检索“普通”方法,而不是从该类的实例中检索,则会得到一个“未绑定的方法” – 即一个对象是一个函数的包装器,但它不会自动添加类本身,也没有任何实例作为调用时的第一个参数.因此,如果要调用“未绑定方法”,则必须手动将其类的实例作为其第一个参数传递.
另一方面,如果手动调用类方法,则该类将作为第一个参数填写:
>>> 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调用类的元类(通常是内置类型) – 并将其作为参数传递给它,名称,基类和类体字典.这个调用产生一个类 – 在Python中,它是一个类的对象,因为一切都是对象.
现在,Python有一些很好的自定义属性访问方式 – 所谓的“描述符”.描述符是定义名为__get __(或__set__或__del__但我们不关心这些的方法)的方法的任何对象.当在Python中访问类或对象的属性时,将返回该属性引用的对象 – 除非它是类属性,并且该对象是描述符.在这种情况下,Python不是返回对象本身,而是在该对象上调用__get__方法,而是返回其结果.例如,内置属性只是一个同时实现__set __,__ get__和__del__的类.
现在,在检索属性时会发生什么,它的主体上的任何函数(或类方法或未绑定方法,如数据模型所述)都具有__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>
至于“类方法”,这些只是不同类型的对象,它们使用内置类方法显式修饰 – 调用__get__时返回的对象是原始函数的包装器,它将填充cls作为第一个参数随传随到.
标签:python-datamodel,python,oop,object,methods 来源: https://codeday.me/bug/20190826/1731148.html