JPNotADragon JPNotADragon - 1 year ago 54
Python Question

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

I'm getting a

Can't set attribute
error when I'm using the
operator on a read-only property that is of a type for which I've defined a

Simplified (but runnable) version of my code:

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

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

def on_mouseenter(self): return self._on_mouseenter

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

The last line produces the error. It goes away if I add the following line to the definition of

def on_mouseenter(self, value): pass

(Runnable at

This behaviour seems strange on two accounts. First, I thought that Python passes objects by reference, so why should the property have to be readable? And second, how come that my dummy setter even works?

Max Max
Answer Source

__iadd__ returns a replacement object to be rebound to the variable. This of course requires a setter.

In this case it works because you're ignoring the set, but still leaving the original object in place, which you've changed in place.

This behavior is required because some objects are immutable, but in place add still works on them.

i += 5 takes the number i is bound to, adds 5 to it, and rebinds i to the NEW result number. That is, it is exactly equivalent to i = i + 5, which has an assignment in it.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download