在Python中修改类常量

时间:2017-08-16 03:06:51

标签: python class class-constants

在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的{​​{1}},而是更改类X本身的实例X。以下代码更改了实例_CON的{​​{1}}而不是类x的更改。

X

5 个答案:

答案 0 :(得分:1)

_CON是类级变量,而不是实例级变量。如果您在课程中更改_CON,那么{X}的所有实例的_CON值都会发生变化。如果_CON的值不是静态的,那么我会包括它作为实例级变量,而不是将其定义为类变量。

答案 1 :(得分:1)

实际上是。分配给实例属性时,将屏蔽类属性。

因此,如果您执行C()._CON,那么您将引用实例命名空间,而如果您执行C._CON则指的是类命名空间。您可以指定实例和类属性未被触及。

c = C()
c._CON = random()

您可以通过self.__class__._CONtype(self)._CON

从实例访问类命名空间

这些都没有经过测试。

请注意_CONX.__init__未全局定义,因此您应该在NameError: global name _CON is not defined行收到x = X(2)错误。

还有另一个问题,因为您在_CON中使用__init__,在实例化后更改它将对y属性没有影响,因为此值已经计算过。在这种情况下,最好的做法是扩展X类并自定义_CON属性。

class Y(X):
    _CON = 3
y = Y(2)

答案 2 :(得分:1)

正如我在this comment中所说的,我将在此处进行扩展,如果OP希望能够动态更改X._CON,即使在实例化x = X(var)之后并且没有编写新的然后,一种方法可能是y propertyvar这样的实例属性:

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

N.B。:正如其他人已经指出并且我认为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._CONself._CON会发生什么变化在设置实例属性X._CONx._CON之前或之后。我将留下这些例子供读者探讨。

答案 3 :(得分:0)

  

是否可以更改X实例的常量_CON。

不。如果需要,您必须使用self.con等实例变量。

在您的示例中,_CON附加到班级X。要将其附加到实例,必须使用self

答案 4 :(得分:-1)

不,从实例/对象中无法更新类变量。因为它是设计的,所有对象必须是恒定的。虽然存在一些技巧(创建一个更新变量的类方法,或者像往常一样使用 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次(有人说不要碰它......)