gpt4 book ai didi

python - Python中的装饰器@staticmethod是如何去掉实例对象的?

转载 作者:太空宇宙 更新时间:2023-11-03 14:53:42 24 4
gpt4 key购买 nike

据我所知,装饰器是一个函数,它将另一个函数作为参数,对其执行一些操作然后返回它。

说到装饰器@staticmethod,装饰器到底做了什么来消除默认传递的实例对象?

最佳答案

staticmethod 装饰器返回一个staticmethod 对象。该对象实现了 descriptor protocol , 和函数一样。

它所做的并不是摆脱实例,而是 staticmethod.__get__ 忽略 绑定(bind)并只返回未改变的函数对象。对于常规函数,function.__get__ 将通过返回一个方法对象(然后跟踪实例和函数以在调用时将它们组合起来)来进行绑定(bind)。

您可以通过手动调用描述符协议(protocol)来重现此内容:

>>> class Demo:
... def regular(self):
... pass
... @staticmethod
... def static():
... pass
...
>>> Demo.__dict__['regular'] # bypass __getattribute__
<function Demo.regular at 0x108515268>
>>> Demo.__dict__['static'] # bypass __getattribute__
<staticmethod object at 0x1084d4f60>
>>> Demo.__dict__['regular'].__get__(Demo()) # descriptor protocol, pass in an instance
<bound method Demo.regular of <__main__.Demo object at 0x1084e2668>>
>>> Demo.__dict__['static'].__get__(Demo()) # descriptor protocol, pass in an instance
<function Demo.static at 0x1085152f0>

通过 Demo.__dict__ 访问 Demo 类的属性,我们绕过了通常由 __getattribute__ 方法强制执行的描述符协议(protocol)。如您所见,对于常规方法,返回一个 function 对象,但对于 static,会找到一个 staticmethod 对象。

调用 .__get__(Demo()) 来调用描述符协议(protocol),然后分别生成一个方法对象和未更改的函数对象。这正是在实例上直接访问相同名称所产生的结果:

>>> Demo().regular
<bound method Demo.regular of <__main__.Demo object at 0x1084dde10>>
>>> Demo().static
<function Demo.static at 0x1085152f0>

请注意,相同的协议(protocol)也是 classmethod 对象被传递 type(instance) 而不是实例作为第一个参数的原因,也是为什么 property 对象在访问时调用底层函数。

关于python - Python中的装饰器@staticmethod是如何去掉实例对象的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44285286/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com