Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 14, 2017 08:25:33

OldBean
Зарегистрирован: 2017-01-14
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Некорректная работа сеттеров и геттеров в Python 2.7

При присваивании атрибуту (свойству) объекта какого-нибудь значения, например, вот так

 sd.q = 52
сеттер не вызывается, а просто создается новая переменная в объекте. Это происходит в Python 2.7. В третьем питоне все работает нормально.

Кто-нибудь сталкивался с такой проблемой? Как ее можно “зафиксить” во втором питоне? Чтобы пользоваться именно свойствами, а не методами. Или это - хороший повод переползать на третий питон?
————————
Текст тестового примера (файл test.py) ниже:

 #coding:utf-8
class SD:
  def __init__(self):
    self._q = 0
  @property
  def q(self):
    print("getter")
    return self._q
  @q.setter
  def q(self, val):
    print("setter (%d)" % (val))
    self._q = val
if __name__ == "__main__":
  sd = SD()
  print(sd.q)
  sd.q = 52
  print(sd.q)
В третьем питоне все работает правильно. Пример сессии:
 pi@pi:~python3 test.py 
getter
0
setter (52)
getter
52
А во втором питоне, геттер вызывается только один раз в начале. А потом, при присваивании, видимо просто создается новая переменная в объекте и сеттеры и геттеры перестают вызываться:
 pi@pi:~python test.py 
getter
0
52

Офлайн

#2 Янв. 14, 2017 08:55:31

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

Некорректная работа сеттеров и геттеров в Python 2.7

В третьем питоне все объекты нового типа, во втором - только унаследованные от object, рекомендую ВСЕГДА наследоваться от object, чтобы не ломать потом себе голову такими якобы “багами”

 class SD(object):



Офлайн

#3 Янв. 14, 2017 10:11:53

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Некорректная работа сеттеров и геттеров в Python 2.7

Или

 #
class SD:
  def __init__(self):
    self._q = 0
  @property
  def q(self):
    print("getter")
    return self._q
  @q.setter
  def new_q(self, val):
    print("setter (%d)" % (val))
    self._q = val

Хотя лучше, как сказал FishHook

Офлайн

#4 Янв. 14, 2017 10:43:59

OldBean
Зарегистрирован: 2017-01-14
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Некорректная работа сеттеров и геттеров в Python 2.7

FishHook
рекомендую ВСЕГДА наследоваться от object, чтобы не ломать потом себе голову такими якобы “багами”
FishHook, спасибо за совет! Ура! Теперь работает. Но почему "якобы баг". Баг он и есть баг. Еще раз спасибо!

Офлайн

#5 Янв. 14, 2017 10:50:16

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Некорректная работа сеттеров и геттеров в Python 2.7

Потому, что в классах старого и нового стиля по-разному формируются пространства имен

Ну и вот пример из официальной документации

 #
class C(object):
    def __init__(self):
        self._x = None
    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x
    @x.setter
    def x(self, value):
        self._x = value
    @x.deleter
    def x(self):
        del self._x

Претензии к языку если Вы не желаете читать документацию предъявлять все же не стоит

Отредактировано 4kpt_IV (Янв. 14, 2017 10:54:14)

Офлайн

#6 Янв. 14, 2017 12:38:19

OldBean
Зарегистрирован: 2017-01-14
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Некорректная работа сеттеров и геттеров в Python 2.7

4kpt_IV
Претензии к языку если Вы не желаете читать документацию предъявлять все же не стоит
Да какие претензии!? Мне очень нравится питон, хотя, к сожалению, писать на нем приходится не так часто. Я просто не знал, что при объявлении класса нужно обязательно и явно указывать Object.

Скорее это (если в официальной документации про Object написано явно) претензия к классикам жанра (фрагмент из книги Лутца “Изучаем Python” 4-е изд").

Офлайн

#7 Янв. 14, 2017 13:32:40

4kpt_IV
Зарегистрирован: 2016-01-08
Сообщения: 999
Репутация: +  49  -
Профиль   Отправить e-mail  

Некорректная работа сеттеров и геттеров в Python 2.7

В 2.Х существуют классы старого и нового стиля. Старого - без object, а нового с object. У них разное поведение вплоть до механизма наследования. В 3.Х от старого стиля отказались и, так как там классы все одного стиля, явное указание object потеряло необходимость, так как это стало поведением по-умолчанию.

Отредактировано 4kpt_IV (Янв. 14, 2017 13:33:52)

Офлайн

#8 Янв. 14, 2017 13:46:47

OldBean
Зарегистрирован: 2017-01-14
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Некорректная работа сеттеров и геттеров в Python 2.7

А… Я таких тонкостей не знал. Вот теперь все встало на место. Спасибо за пояснения!

Офлайн

#9 Янв. 14, 2017 15:12:28

Stright
От: Кострома
Зарегистрирован: 2015-01-20
Сообщения: 139
Репутация: +  16  -
Профиль   Отправить e-mail  

Некорректная работа сеттеров и геттеров в Python 2.7

OldBean
Скорее это (если в официальной документации про Object написано явно) претензия к классикам жанра (фрагмент из книги Лутца “Изучаем Python” 4-е изд").
Ваши претензии необоснованы В книге автор четко разделяет классы старого и нового стиля, более того, весь раздел про классы построен на их сравнении, а двумя страницами выше приведенного фрагмента он пишет как раз то, что вам сказал 4kpt_IV

Отредактировано Stright (Янв. 14, 2017 15:40:58)

Офлайн

#10 Янв. 14, 2017 16:27:25

OldBean
Зарегистрирован: 2017-01-14
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Некорректная работа сеттеров и геттеров в Python 2.7

Да. Вы правы.
Вот и чудесно - теперь и Лутц реабилитирован! Можно спать спокойно.

Конечно, нужно внимательней и, главное, подряд (!) читать тексты книжек. К сожалению, это не всегда удается. Особенно когда пользуешься языком изредка. Обычно берешь пример из знакомой книжки, модифицируешь под свою задачу. А тут неожиданно взял да наступил на такие упругие грабли! У меня за этим сеттером стоит длинный обмен с микроконтроллером, а само свойство (точнее его значение) вообще не хранится на том компьютере, где работает питон. Там был довольно большой кусок уже работающего кода. Но захотелось все красиво оформить. Через классы и свойства. Поэтому пока локализовал баг - все проклял. Но очень рад, что проблема оказалась пустяковой!

Ну вот, вроде бы все вопросы “разрешены”. Тему можно закрывать. Еще раз спасибо всем за помощь!

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version