Вы можете сделать это несколькими способами, возможно, они не являются «общими», но они все еще Pythonic
.
Во-первых, __dict__
Рассмотрим этот простой код :
class Lines:
pass
line1 = Lines()
Теперь я хочу изменить атрибут xy
, я имею в виду установить его как 10
. Как только Python является динамическим c и все в Python является объектом, я могу это сделать, посмотрите:
class Lines:
pass
line1 = Lines()
line1.xy = 10
print(f"line1.xy = {line1.xy}") #Output: line1.xy = 10
Что? Как я могу установить атрибут, который не существует ?! Это просто, __dict__
. В нем хранятся все атрибуты, установленные в экземпляре.
class Lines:
pass
line1 = Lines()
line1.xy = 10
print(f"xy = {line1.xy}") #Output: xy = 10
print(f"__dict__ = {line1.__dict__}") #Output: __dict__ = {'xy': 10}
Итак, если __dict__
хранит атрибуты, установленные в экземпляре, каково состояние __dict__
до того, как я установил какой-либо атрибут ?! Как вы можете сделать вывод, он начинается пустым.
Таким образом, вы должны помнить, что __dict__
не показывает доступные атрибуты, но атрибуты, которые были установлены, и не имеет значения, существуют ли эти атрибуты или не в main class
Однако, когда я печатаю line1.__dict__
, они не отображаются в доступных атрибутах.
Фактически все атрибуты в __dict__
доступны через него, но если вы попытаетесь получить любой другой атрибут, которого нет в __dict__
, но определенный в классе, вы можете получить его. КАК? Взгляните:
class Lines:
x1 = 3
x2 = 7
line1 = Lines()
print(f"__dict__ = {line1.__dict__}") #Output: __dict__ = {}
print(f"x1 = {line1.x1}") #Output: x1 = 3
print(f"x2 = {line1.x2}") #Output: x2 = 7
print(f"__dict__ = {line1.__dict__}") #Output: __dict__ = {}
line1.x1 = 9 #Setting x1, so it will be stored at __dict__
print(f"__dict__ = {line1.__dict__}") #Output: __dict__ = {'x1': 9}
print(f"x1 = {line1.x1}") #Output: x1 = 9
print(f"x2 = {line1.x2}") #Output: x2 = 7
print(f"test = {line1.test}") #Output: AttributeError
Что здесь делает python ?! Python сначала идет к __dict__
и пытается найти атрибуты x1
и x2
, поэтому, если он их там не находит, то он переходит к main class
, если он их находит, он их возвращает для вас, если нет Python Поднять AttributeError
.
__dict__
- это круто, это позволяет вам делать много вещей. Поскольку любое значение атрибута хранится в __dict__
, вы можете получить его значение напрямую по нему, посмотрите:
example = line1.__dict__['x1']
print(f"__dict__['x1'] = {example}") #Output: __dict__['x1'] = 9
Ваши проблемы и вопросы
Дискурс о коде pythoni c действительно Интересно, но мы должны спросить себя, являются ли эти коды python или нет, что я имею в виду, если какой-то код python и нет "improvisation"
, так что это pythoni c, даже если этот код не такой например, методы getattr()
, setattr()
и delattr()
, иногда их использование более практично, чем "dotted notation"
, потому что они более надежны для понимания, особенно когда вы глубоко погружаетесь в то, что делаете и вы отлаживаете. (По крайней мере, я так думаю)
Так что все идет вокруг того, что вы делаете и что вы хотите сделать. Представьте, что у вас высококачественный код и вы используете не очень распространенные функции, не так ли, Pythoni c ?! Для ясности представьте, что вы пишете счетчик, который увеличивается каждый раз, когда выполняется транзакция, поэтому вместо этого вы используете обычный способ count += 1
, вы go выше и используете itertools.count()
, без сомнения, у вас есть высококачественный код , даже если люди обычно не используют этот модуль, вы можете узнать больше об этом здесь: itertools - Функции, создающие итераторы для эффективного цикла .
Итак, давайте go к коду: как вы видите, это еще один способ решения этой проблемы.
class Lines:
def __init__(self, points):
self.x1 = points[0]
self.y1 = points[1]
self.x2 = points[2]
self.y2 = points[3]
self.length = self._length()
self.slope = self._slope()
self.y_intercept = self._y_intercept()
def _length(self):
return round(((self.x2-self.x1)**2 + (self.y2-self.y1)**2) ** 0.5, 2)
def _slope(self):
return round((self.y2 - self.y1)/(self.x2-self.x1),1)
def _y_intercept(self):
return self.y1 - self.slope*self.x1
line1 = Lines([0,0,2,4])
print(line1.length)
print(line1.slope)
print(line1.y_intercept)
Ваше решение с использованием Read-Only property
действительно интересно, на самом деле оно даже позволяет вы также работаете с кешем (если мы напишем, конечно же!), поэтому вам не нужны атрибуты cal c you length
, slope
и y_intercept
каждый раз, когда вы вызываете эти переменные, вы можете cal c их значения только при изменении значения атрибута points
.
Надеюсь, вам поможет, пока!
Don't use "improvisation", use Python.