Изменить константу класса в 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 раз подумать, прежде чем обновлять все, что начинается с подчеркивания (кто-то говорит: не трогайте это...)

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