python类中的静态变量

时间:2018-03-09 18:00:20

标签: python class object instance

我在理解Python类中的静态变量概念时遇到了问题。根据{{​​3}},每当我们在方法之外和python类中定义变量时,此变量都是静态的。这意味着可以访问此变量,而无需从类中实例化对象,并且可以直接通过类名访问。 例如:

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 

您可以看到我们可以通过实例对象和类名访问静态变量i。但是,当我们更改实例对象的i值时,它不会影响类的值(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]

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

3 个答案:

答案 0 :(得分:4)

通常分配给实例属性设置实例属性。一旦有实例属性,它就会掩盖类属性。

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

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

那是因为您只是读取对列表的instance.i引用,以便打印它,并找到list.append()方法。您在任何时候都没有为instance.i属性引用设置新值。

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

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

>>> 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都只是对同一列表对象的不同引用,您可以通过任何这些引用修改(mutate)该列表对象。

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

答案 1 :(得分:1)

instance.i.append(13)

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

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

instance.i = [13]

然后你会看到你期待的东西。

答案 2 :(得分:-2)

在实例化期间,对象在实例化时接收每个类属性的副本(或多或少)。这就是为什么你可以在不影响课程的情况下访问和改变实例上的值,并且签证/反之亦然。

其中list被修改的第二点,似乎是从实例到类的反向是由于list的可变性,并且类似于默认参数经常遇到的问题,{ {3}}