簡體   English   中英

將函數分配給對象屬性

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM