簡體   English   中英

如何在沒有設置器的屬性上使用+ =運算符?

[英]How to use the += operator on a property that doesn't have a setter?

在只讀屬性上使用+=運算符時,出現Can't set attribute錯誤,該屬性的類型已定義__iadd__()方法。

我的代碼的簡化(但可運行)版本:

class Emitter(list):
    def __iadd__(self, other):
        self.append( other )
        return self

class Widget:
    def __init__(self):
        self._on_mouseenter = Emitter()

    @property
    def on_mouseenter(self): return self._on_mouseenter


my_widget = Widget()
my_widget.on_mouseenter += lambda source: print("on_mouseenter!")

最后一行產生錯誤。 如果Widget下行添加到Widget的定義中,它將消失:

@on_mouseenter.setter
def on_mouseenter(self, value): pass

(可在https://repl.it/EONf/0運行

在兩個帳戶上,此行為似乎很奇怪。 首先,我認為Python通過引用傳遞對象,那么為什么該屬性必須是可讀的? 其次,我的虛擬塞特犬甚至如何工作?

__iadd__將替換對象返回到該變量。 當然,這需要二傳手。

在這種情況下,它起作用是因為您忽略了該集合,但仍將原始對象保留在原位置,而您將其更改了。

因為某些對象是不可變的,所以必須執行此行為,但是在適當的位置添加仍然可以對它們起作用。

i += 5接受與我綁定的數字,將其加5,然后將i重新綁定到新的結果數字。 也就是說,它完全等於i = i + 5 ,其中有一個賦值。

這是由Python的擴展賦值運算符的工作方式引起的。 調用適當的特殊方法后 ,它們將返回值分配給運算符左側的對象。

如果x是具有__iadd__()方法的類的實例,則x += y等效於x = x.__iadd__(y) 否則,將x.__add__(y)y.__radd__(x)視為與x + y的求值相同。

因此

my_widget.on_mouseenter += lambda source: print("on_mouseenter!")

相當於

my_widget.on_mouseenter = my_widget.on_mouseenter.__iadd__(lambda source: print("on_mouseenter!"))

並且您需要一個二傳手來執行分配。 但是,它不需要執行任何操作,因為__iadd__方法已定義並就地修改了列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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