據我所知,裝飾器是一個函數,它接受另一個函數作爲參數,對它執行一些操作然後返回它。Python中的裝飾器@staticmethod如何擺脫實例對象?
說到decorator @staticmethod,裝飾器究竟做了什麼來消除默認傳遞的實例對象?
據我所知,裝飾器是一個函數,它接受另一個函數作爲參數,對它執行一些操作然後返回它。Python中的裝飾器@staticmethod如何擺脫實例對象?
說到decorator @staticmethod,裝飾器究竟做了什麼來消除默認傳遞的實例對象?
staticmethod
裝飾工返回一個staticmethod
對象。該對象實現了descriptor protocol,與功能一樣。
這是幹什麼的不是它將實例拋棄,而是將staticmethod.__get__
完全忽略綁定,只是返回未改變的函數對象。對於常規函數,function.__get__
將通過返回方法對象(然後跟蹤實例和函數以在調用時組合它們)來綁定。
可以通過手動調用描述符協議重現此:
>>> 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__
方法執行。如您所見,對於常規方法,函數返回對象,但對於static
,則會找到staticmethod
對象。
調用.__get__(Demo())
來調用描述符協議,然後分別產生一個方法對象和未改變的函數對象。這正是直接訪問同一個名字上的一個實例產生:
>>> Demo().regular
<bound method Demo.regular of <__main__.Demo object at 0x1084dde10>>
>>> Demo().static
<function Demo.static at 0x1085152f0>
需要注意的是相同的協議也是classmethod
對象傳遞type(instance)
而不是實例作爲第一個參數的原因,也是爲什麼property
對象在訪問時調用底層函數。
查看位於底部某處的Python實現:https://docs.python.org/3/howto/descriptor.html#static-methods-and-class-methods – vaultah