-3

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

x = X(2)
x._CON = 3
x.__init__(2)
4

5 回答 5

1

实际上是的。当您分配给实例属性时,您会屏蔽类属性。

因此,如果您这样做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)

还有另一个问题,因为你使用_CONin __init__,在实例化它之后改变它不会对y属性产生影响,因为这个值已经被计算过了。在这种情况下,更好的做法是扩展X类并自定义_CON属性。

class Y(X):
    _CON = 3
y = Y(2)
于 2017-08-16T03:34:21.463 回答
1

正如我在此评论中所说的,我将在这里扩展,如果 OP 希望能够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

注意:正如其他人指出的那样,我认为 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._CONx10._CON. 我会把这些例子留给读者去探索。

于 2017-08-17T16:58:16.707 回答
1

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

于 2017-08-16T03:14:34.910 回答
0

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

没有。如果你想要这个,你必须使用一个实例变量,比如self.con.

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

于 2017-08-16T03:14:17.927 回答
-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 次(有人说不要碰它……)

于 2017-08-16T03:12:33.280 回答