[英]Assigning a function to an object attribute
根據我對Python 數據模型的理解,特別是“實例方法”小節,每當您讀取值為“用戶定義函數”類型的屬性時,就會產生一些魔法,您將獲得綁定實例方法而不是實際,原函數。 這就是為什么在調用方法時不顯式傳遞self
參數的原因。
但是,我希望能夠用具有相同簽名的函數替換對象的方法:
class Scriptable:
def __init__(self, script = None):
if script is not None:
self.script = script # replace the method
def script(self):
print("greetings from the default script")
>>> scriptable = Scriptable()
>>> scriptable.script()
greetings from the default script
>>> def my_script(self):
... print("greetings from my custom script")
...
>>> scriptable = Scriptable(my_script)
>>> scriptable.script()
Traceback (most recent call last):
...
TypeError: script() takes exactly 1 positional argument (0 given)
我正在創建Scriptable
的實例,並將其script
屬性設置為具有單個參數的用戶定義函數,就像類中定義的那樣。 因此,當我閱讀scriptable.script
屬性時,我希望魔法能夠發揮作用並為我提供一個不帶參數的綁定實例方法(就像我沒有替換script
時得到的那樣)。 相反,它似乎返回了我傳入的完全相同的函數、 self
參數等等。 方法綁定魔法沒有發生。
為什么當我在類聲明中定義方法時,方法綁定魔法起作用,而當我分配屬性時卻不起作用? 是什么讓 Python 以不同的方式對待這些情況?
如果有任何區別,我正在使用 Python3。
這是你如何做到的:
import types
class Scriptable:
def __init__(self, script = None):
if script is not None:
self.script = types.MethodType(script, self) # replace the method
def script(self):
print("greetings from the default script")
正如 ba__friend 在評論中指出的那樣,方法存儲在class
對象上。 當您從實例訪問屬性時,類對象上的描述符將函數作為綁定方法返回。
當你將一個函數分配給一個instance
時,沒有什么特別的事情發生,所以你必須自己包裝這個函數。
感謝 Alex Martelli 的回答,這里是另一個版本:
class Scriptable:
def script(self):
print(self)
print("greetings from the default script")
def another_script(self):
print(self)
print("greetings from the another script")
s = Scriptable()
s.script()
# monkey patching:
s.script = another_script.__get__(s, Scriptable)
s.script()
看這個:
>>> scriptable = Scriptable()
>>> scriptable.script
<bound method Scriptable.script of <__main__.Scriptable instance at 0x01209DA0>>
>>> scriptable = Scriptable(my_script)
>>> scriptable.script
<function my_script at 0x00CF9730>
聲明self.script = script
只創建一個類對象的屬性,沒有任何“魔法”。
語句def script(self):
在類定義中創建一個描述符 - 特殊對象,它實際管理帶有self
參數的所有內容。
您可以在提到的數據模型參考中閱讀有關 Python 中描述符的更多信息: implementation-descriptors 。
來自 Raymond Hettinger 的另一篇關於 Python 中描述符的很棒的文章:描述符的操作指南。
我真的無法回答你的問題為什么它會這樣,你必須問 Guido van Rossum,但我可以給你一個可能的解決方法:
class Scriptable:
def __init__(self, script = None):
self._script = script # replace the method
def script(self):
if self._script: return self._script(self)
return self._defaultscript()
def _defaultscript(self):
print("greetings from the default script")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.