Python игнорирует сеттер

Я новичок в Python, и я пытаюсь создать класс с get / set в качестве свойства. Я скопировал простой пример из интернета, и кажется, что Python игнорирует мой установщик. Я делаю что-то очень глупое, потому что я не понимаю, почему это не работает.

Я использую Python 2.6.6 в Linux.

Спасибо

#!/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

Единственное, что у меня есть в командной строке, это то, что она печатает -5555. Это полностью игнорирует мой сеттер.

Это сводит меня с ума, есть идеи?

1 ответ

Решение

Проблема в том, что вы определили Celsius как класс старого стиля.

Документация для property делает это довольно ясно:

Возврат атрибута свойства для классов нового стиля (классов, производных от object).

Причина этого в том, что @property работает, создавая дескриптор, и, как говорят в документах по классам нового стиля:

Основной мотивацией для введения классов нового стиля является предоставление единой объектной модели с полной метамоделью. Он также имеет ряд практических преимуществ, таких как возможность создавать подклассы для большинства встроенных типов или введение "дескрипторов", которые обеспечивают вычисляемые свойства.


Чтобы это исправить, просто сделайте Celsius класс нового стиля, наследуя от object:

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

Конечно, если вы обновитесь до Python 3, проблема исчезнет, ​​потому что все классы - это классы нового стиля. В частности, если вы не укажете другие базовые классы, вы получите object в качестве базового класса, 1 так class Spam:, class Spam():, а также class Spam(object): все означают то же самое в 3.x, что class Spam(object): подразумевается в 2.x.


1. Это на самом деле два изменения под прикрытием. Во-первых, class Statement всегда компилируется в вызов метакласса, а не в специальную конструкцию класса старого стиля. Во-вторых, метакласс по умолчанию, type , заполняет (object,) если вы передадите ему пустой список баз. Но вам редко нужно понимать что-либо из этого, поэтому в сноске болит зрение.

Другие вопросы по тегам