[英]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
在兩個帳戶上,此行為似乎很奇怪。 首先,我認為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.