-2

@property defined as int

The following code is taken from Python Docs:

class Parrot(object):
    def __init__(self):
        self._voltage = 100000

    @property
    def voltage(self):
        """Get the current voltage."""
        return self._voltage

When I run:

parrot = Parrot()
print(parrot.voltage)
parrot.voltage = 100
print(parrot.voltage)

I get the following output (as expected, as no setter is defined)

{0: 100000}
Traceback (most recent call last):
   File "prop.py", line 13, in <module>
     parrot.voltage = 100
 AttributeError: can't set attribute

@property defined as dict

However, if I define self._voltage = {} the property becomes writeable:

class Parrot(object):
    def __init__(self):
        self._voltage = {}
        self._voltage[0] = 100000

    @property
    def voltage(self):
        """Get the current voltage."""
        return self._voltage

parrot = Parrot()
print(parrot.voltage)
parrot.voltage[0] = 100
print(parrot.voltage)

The output is then:

{0: 100000}
{0: 100}

Same behavior in Python 2.7.9 and Python 3.4.3. Why is the property writeable, even if no setter is explicitly defined in the code? Here it was proposed to subclass dict to get this behavior. However, it seems that this not required.

Community
  • 1
  • 1
Stifi
  • 3
  • 2
  • Because now you're updating the object returned by the getter. A property will only take care of `parrot.voltage = 100` not `parrot.voltage[0] = 100`. – Ashwini Chaudhary Jul 06 '15 at 10:10
  • 1
    You are *not setting the property*. You are mutating a mutable object. Same with any other object that can be mutated; list, set, another custom class instance. – Martijn Pieters Jul 06 '15 at 10:11

1 Answers1

2

You are not setting the property. You are manipulating a mutable object.

The assignment is not on the property itself, but on a subscription, the [..] part addresses a dictionary key. You could assign the property to a new name and still manipulate that dictionary:

parrot = Parrot()
parrot_voltage = parrot.voltage
parrot_voltage[0] = 100

but you cannot set the property to a new dictionary or a different type of object altogether. This applies to all mutable objects used in a property; lists, sets, instances, etc.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343