Изменить константу класса в Python
В Python я определяю класс:
class X():
_CON = 0
def __init__(self, var):
self.y = var*self._CON
Можно ли изменить константу _CON
например X
? Например, я пытаюсь сделать следующее
X._CON = 3
x = X(2)
a = x.y
Я жду _CON
должно быть изменено с 0 на 3 и, таким образом, self.y = var*_CON = 2*3 = 6
, Как правильно сделать это, если не создать новый класс?
Редактировать:
Я нашел ответ. Мой второй код работает. Однако, это не меняет _CON
экземпляра x
класса X
но это класса X
сам. Следующие изменения кода _CON
экземпляра x
не из класса X
,
x = X(2)
x._CON = 3
x.__init__(2)
5 ответов
_CON
является переменной уровня класса, а не переменной уровня экземпляра. Если вы измените _CON
в вашем классе, то значение _CON
будет меняться для всех экземпляров вашего класса X. Если значение _CON
не будет статичным, тогда я бы включил его в качестве переменной уровня экземпляра вместо определения в качестве переменной класса.
На самом деле это так. Когда вы присваиваете атрибуту экземпляра, вы маскируете атрибут класса.
Так что если вы делаете C()._CON
вы ссылаетесь на пространство имен экземпляра, если вы делаете C._CON
вы ссылаетесь на пространство имен класса. Вы можете назначить экземпляр и атрибут класса не трогать.
c = C()
c._CON = random()
Вы можете получить доступ к пространству имен класса из экземпляра: self.__class__._CON
или же type(self)._CON
Ничего из этого не было проверено.
Обратите внимание, что _CON
не определен глобально в X.__init__
так что вы должны получить NameError: global name _CON is not defined
ошибка в x = X(2)
линия.
И есть еще одна проблема, так как вы используете _CON
в __init__
изменение его после создания экземпляра не повлияет на y
атрибут, потому что это значение уже было вычислено. В этом случае лучше всего продлить X
класс и настроить _CON
приписывать.
class Y(X):
_CON = 3
y = Y(2)
Как я уже сказал в этом комментарии, который я здесь более подробно расскажу, если ОП хочет изменить X._CON
на лету, даже после создания экземпляра x = X(var)
и без написания нового класса, то один из способов может быть сделать y
собственность и var
атрибут экземпляра, подобный этому:
class X(object):
_CON = 0
def __init__(self, var):
self.var = var
@property
def y(self):
return self.var * X._CON
затем...
>>> x = X(2)
>>> x.y # returns 0
>>> X._CON = 3
>>> x.y # returns 6
NB: Как указали другие, и я думаю, что OP уже обнаружил, этот пример использует атрибут класса X._CON
и изменения атрибута класса затронут все экземпляры этого класса. Например, выполнение следующего после создания экземпляра x = X(var)
сверху, значение X._CON
будет еще 3; это не будет 0.
Пожалуйста, обратите особое внимание на разницу между капиталом X
класс и мало x
пример в примерах ниже:
>>> x._CON = 23 # <-- doesn't affect x.y b/c x.y = x.var * X._CON
>>> x.y # still returns 6 b/c X._CON = 3 still
>>> x10 = X(10)
>>> x10.y # returns 30 b/c X._CON = 3
>>> x._CON # returns 23
>>> x10._CON # returns 3 since we changed X._CON to 3
>>> X._CON # returns 3 <-- this is the **class** attribute
Поэтому, если вы хотите значение _CON
чтобы быть конкретным для каждого экземпляра, а затем использовать self._CON
вместо X._CON
, Начиная заново...
class X(object):
_CON = 0
def __init__(self, var):
self.var = var
@property
def y(self):
return self.var * self._CON # <-- use **instance** attribute
затем...
>>> x = X(2)
>>> x.y # returns 0
>>> x._CON = 3 # <-- use **instance** attribute
>>> x.y # returns 6
>>> x10 = X(10)
>>> x10.y # returns 0 b/c x10._CON = X._CON = 0
>>> x10._CON = 7 # <-- use **instance** attribute
>>> x10.y # returns 70
>>> x._CON # returns 3
>>> x10._CON # returns 7
>>> X._CON # returns 0
Есть еще несколько вариантов, например, что происходит с атрибутами экземпляра x._CON
а также x10._CON
во втором примере с использованием self._CON
если вы измените атрибут класса X._CON
либо до, либо после установки атрибутов экземпляра x._CON
или же x10._CON
, Я оставлю эти примеры на усмотрение читателя.
Можно ли получить изменение константы _CON для экземпляра X.
Нету. Если вы хотите это, вы должны использовать переменную экземпляра, как self.con
,
В вашем примере _CON
прикреплен к классу X
, Чтобы прикрепить его к экземпляру, вы должны использовать self
,
Нет, из экземпляра / объекта вы не можете обновить переменную класса. Потому что это по замыслу должно быть постоянным для всего объекта. Хотя некоторые хитрости существуют (создайте метод класса для обновления переменной или, как обычно, используйте метод init.)..
class MyClass:
_CON = 1
@classmethod
def update(cls, value):
cls._CON += value
def __init__(self,value):
self.value = value
self.update(value)
a = MyClass(1)
print (MyClass._CON) #o/p: 2
И вы должны 10 раз подумать, прежде чем обновлять все, что начинается с подчеркивания (кто-то говорит: не трогайте это...)