我做了一点实验.通过检查__dict__类或实例,我可以看到某些方法有类型function和一些bound method.实验很乱,我无法解决以下问题.
在Python 3中,类或实例的方法之间有什么区别,它们是"函数",哪些是"绑定方法"?
它们是如何分别创建的?
它们可以在类和实例上调用吗?它们是否会被隐含地作为第一个参数的实例?
"绑定方法"是类的属性还是类的实例?
谢谢.
这个答案将是技术性的,我希望它仍然可以理解.问题是需要知道描述符协议才能理解Python中的方法是如何工作的.
Python 3中的所有函数都是描述符,准确地说它们是非数据描述符.这意味着他们实现了一种__get__方法 - 但没有__set__方法.
这很有趣,因为如果在类或实例上查找,描述符可以(几乎)执行任何操作.
通过Pythons数据模型中__get__方法的定义:
object.__get__(self, instance, owner)调用以获取所有者类(类属性访问)或该类的实例(实例属性访问)的属性.
owner永远是老板级,同时instance是该属性被访问过,或实例None时,属性可以通过访问owner.此方法应返回(计算)属性值或引发AttributeError异常.
那么,这与之间的差异做function和bound_method?
它很容易,一个函数通过__get__一个instance=None将返回自己的函数:
>>> def func(x): return x
>>> func.__get__(None, object)
<function __main__.func>
>>> func.__get__(None, object) is func
True
Run Code Online (Sandbox Code Playgroud)
虽然bound_method使用not-None实例访问它是一个if:
>>> func.__get__(object())
<bound method func of <object object at 0x00000155614A0610>>
Run Code Online (Sandbox Code Playgroud)
它基本上只是func存储实例的包装器:
>>> m = func.__get__(object())
>>> m.__self__ # stored instance
<object at 0x155614a0650>
>>> m.__func__ # stored function
<function __main__.func>
Run Code Online (Sandbox Code Playgroud)
但是,在调用时,它会将实例作为第一个参数传递给包装函数:
>>> m()
<object at 0x155614a0650>
Run Code Online (Sandbox Code Playgroud)
因此,bound methods将实例作为第一个参数传递,而functions则不传递(它们需要所有属性).
所以,当你在一个类中的所有正常方法将显示为功能,而所有正常的一个实例的方法会bound methods.
为什么我提到常规方法?因为您可以定义任意描述符.例如,Python内置函数已经包含几个例外:
classmethodstaticmethodproperty (这实际上是一个数据描述符,因此我将在下面的讨论中忽略它)classmethodbound method即使在课堂上查询,s也会显示.这是因为它们在类上是可调用的,并将类传递给函数,无论它们是在类还是实例上调用:
class Test(object):
@classmethod
def func(x):
return x
>>> Test.func
<bound method Test.func of <class '__main__.Test'>>
>>> Test().func
<bound method Test.func of <class '__main__.Test'>>
Run Code Online (Sandbox Code Playgroud)
并且staticmethods总是显示为函数,因为它们从不传递函数的任何附加内容:
class Test(object):
@staticmethod
def func(x):
return x
>>> Test().func
<function __main__.Test.func>
>>> Test.func
<function __main__.Test.func>
Run Code Online (Sandbox Code Playgroud)
所以很容易看到bound method类上的s(例如classmethods),同样也可以function在实例上找到正常的s(例如staticmethods).
| 归档时间: |
|
| 查看次数: |
79 次 |
| 最近记录: |