python 类 中的静态变量

Static variables in python classes

我在理解 Python classes 中静态变量的概念时遇到了问题。根据Static class variables in Python,每当我们在方法外和pythonclass内定义一个变量时,这个变量是静态的。这意味着可以访问此变量而无需从 class 实例化对象,并且可以直接通过 class 名称访问。 例如:

class my_class:

     i=12

     def __init__(self,j):
        self.j=j


instance=my_class(10)

my_class.i:
>12
instance.i:
>12
instance.i=13
instance.i:
>13
my_class.i:
>12 

可以看到我们可以通过实例对象和class名称来访问静态变量i。但是,当我们更改实例对象的 i 的值时,它不会影响 class 的值(my_class.i 仍然是 12)。 另一方面,如果我们使用数组静态变量,情况就会完全不同。 考虑类似的例子:

class my_class:

     i=[]

     def __init__(self,j):
        self.j=j


instance=my_class(10)

my_class.i:
>[]
instance.i:
>[]
instance.i.append(13)
instance.i:
>[13]
my_class.i:
>[13]

您可以看到,当我更改实例对象数组的变量时,它也会影响 class 值。这里发生了什么?如果有人可以帮助我更好地理解这个问题,我将不胜感激,因为它对我来说并不是那么明显。对了,我有Java背景

通常分配给实例属性设置实例属性。一旦有实例属性,它就会屏蔽 class 属性。

所以在你执行instance.i=13之前,实例上没有i属性,只有class。然后,您将实例上的名称 i 绑定到 13,下次查找 instance.i 时会找到该属性,并且不再尝试查找 my_class.i .

但是操作 可变对象 与分配给 class 或实例属性不同。您没有分配给 instance.i,您更改了 my_class.i 引用并通过 instance.i 可见的列表对象。 instance.i 仍然会找到 my_class.i 属性,您从未使用 = 创建 instance.i 属性。

那是因为您只 读取 对列表的 instance.i 引用,以便打印它并找到 list.append() 方法。您绝不会为 instance.i 属性引用设置新值。

列表对象是它自己的对象,您可以通过添加、删除或替换列表的 索引 引用的值来更改该对象。引用该列表的名称或属性无关紧要,您可以对同一个列表有任意数量的此类引用,并且更改列表不会更改这些引用。

尝试创建对列表的更多引用,看看会发生什么:

>>> list_named_i = instance.i
>>> list_named_i
[13]
>>> my_class.i.append(42)
>>> list_named_i
[13, 42]
>>> list_named_i[0] = 81
>>> instance.i
[81, 42]

instance.imy_class.ilist_named_i 都是对同一列表对象的不同引用,您可以通过这些引用中的任何一个修改(变异)该列表对象。

我建议您阅读 Python 名称和属性以及列表等如何工作;参见 Ned Batchelder 的 Facts and myths about Python names and values

在实例化过程中,对象会在实例化时收到每个 class 属性的副本(或多或少)。这就是为什么您可以在不影响 class 和 visa/versa.

的情况下访问和更改实例上的值的原因

你的第二点,其中 list 被修改,似乎从实例到 class 是相反的,这是由于 list 的可变性,并且与经常出现的问题相似遇到默认参数 described here.

instance.i.append(13)

这不会更改变量,它会改变列表对象。变量仍然设置为同一个对象。

如果将变量设置为新列表:

instance.i = [13]

然后你就会看到你所期待的。