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.i
、my_class.i
和 list_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]
然后你就会看到你所期待的。
我在理解 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.i
、my_class.i
和 list_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]
然后你就会看到你所期待的。