Moose1231
Moose1231

Reputation: 9

Python ignores setter

I am new to python and I try to create a class with get/set as property. I have copied a simple example from internet and it seems that Python ignores my setter. Am I doing something very stupid because I don't understand why it does not work.

I am running python 2.6.6 on Linux.

Thanks

#!/usr/bin/python

class Celsius:
    def __init__(self, temperature = 0):
        self._temperature = temperature

    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

    @property
    def temperature(self):
        print("Getting value")
        return self._temperature

    @temperature.setter
    def temperature(self, value):
        if value < -273:
            raise ValueError("Temperature below -273 is not possible")
        print("Setting value")
        self._temperature = value

c = Celsius()

c.temperature = -5555

print c.temperature

The only thing I have in the command line is that it print -5555. It completely ignores my setter.

This is driving me crazy, any ideas?

Upvotes: 0

Views: 198

Answers (1)

abarnert
abarnert

Reputation: 365657

The problem is that you've defined Celsius as an old-style class.

The documentation for property makes this pretty clear:

Return a property attribute for new-style classes (classes that derive from object).

The reason for this is that @property works by building a descriptor, and, as the docs on new-style classes say:

The major motivation for introducing new-style classes is to provide a unified object model with a full meta-model. It also has a number of practical benefits, like the ability to subclass most built-in types, or the introduction of “descriptors”, which enable computed properties.


To fix this, just make Celsius a new-style class, by inheriting from object:

class Celsius(object):
    # all the rest of your code is the same.

Of course if you upgrade to Python 3, the problem goes away, because all classes are new-style classes. In particular, if you don't specify any other base classes, you get object as a base class,1 so class Spam:, class Spam():, and class Spam(object): all mean the same thing in 3.x that class Spam(object): meant in 2.x.


1. This is actually two changes under the covers. First, the class statement always compiles to a call to a metaclass, never to the special old-style class construction. Second, the default metaclass, type, fills in (object,) if you pass it an empty list of bases. But you rarely need to understand any of this stuff, which is why it's in a footnote that hurts your eyes to squint at.

Upvotes: 4

Related Questions