#python #python-3.x #class #properties #python-descriptors
#питон #python-3.x #класс #свойства #python-дескрипторы
Вопрос:
Я хочу создать класс, который имеет множество свойств, которые по большей части будут просто получены и установлены. Вот пример MyClass()
gt;gt;gt; class MyClass(): ... def getx(self): return self.__x ... def setx(self, value): self.__x = value ... def delx(self): del self.__x ... x = property(getx, setx, delx, "I'm the 'x' property.") ... y = property(getx, setx, delx, "I'm the 'y' property.") ... gt;gt;gt; bar = MyClass() gt;gt;gt; bar.x = 'jeff' gt;gt;gt; bar.y = 3 gt;gt;gt; print(bar.x) 3 gt;gt;gt; print(bar.y) 3 gt;gt;gt;
Здесь свойства x и y одинаковы, поэтому, если я хочу, чтобы x и y были уникальными, мне понадобится новый getx/setx/delx для каждого из них.
Этот пример работает лучше.
gt;gt;gt; class MyClassBase(): ... def __init__(self, initval=None): ... self.val = initval ... def __get__(self, obj, objtype): ... return self.val ... def __set__(self, obj, val): ... self.val = val ... gt;gt;gt; class MyClassFinal(): ... x = MyClassBase(1) ... y = MyClassBase('xyzzy') ... gt;gt;gt; foo = MyClassFinal() gt;gt;gt; foo.x = 2 gt;gt;gt; print(foo.x) 2 gt;gt;gt; print(foo.y) xyzzy gt;gt;gt;
Я думаю, что MyClassBase () — это то, что они называют (или эквивалентно) классом дескрипторов. Теперь свойства x, y (и любые другие, которые я решу добавить в MyClassFinal ()), независимы.
Кажется странным, что мне нужно создать MyClassBase() самостоятельно. Разве это (или что-то эквивалентное) уже где-то определено, поэтому мне не нужно создавать свое собственное?
Я также открыт для другого примера того, как создать класс с большим количеством свойств и минимальным количеством кода.
Комментарии:
1. Итак, очевидный вопрос: почему? Если все, что вы делаете, — это боксируете атрибут, какую выгоду вы ожидаете получить?
2. в Python предпочтительнее использовать напрямую
foo.x
безgetx, setx, delx
3. версия с
MyClassBase
хорошей идеей. Некоторые модули используют что — то подобное для собственных задач-т. е.tkinter
имеетStringVar()
IntegerVar()
, и т. Д. иKivy
имеетIntegerProperty()
,ObjectProperty()
и т. Д. И они добавляют больше функций — т. е. они проверяют, правильно ли вы задали тип данных, они также могут запускать внешнюю функцию при изменении значения — поэтому они работают какlistener
.
Ответ №1:
Ааа! Я все слишком усложняю. Очевидно, все, что мне нужно сделать, это:
gt;gt;gt; class MyClassSimple: ... x = 1 ... y = 'blue' ... def __str__(self): ... return f'{self.x}, {self.y}' ... gt;gt;gt; zot = MyClassSimple() gt;gt;gt; print(zot) 1, blue gt;gt;gt; zot.x = 'red' gt;gt;gt; zot.y = 3 gt;gt;gt; print(zot) red, 3