我看到以下Python文档说“在类中定义变量”将是类变量:
“程序员注意:类定义中定义的变量是 类变量;它们由所有实例共享。 “
但是我写了这样的示例代码:
class CustomizedMethods(object):
class_var1 = 'foo'
class_var2 = 'bar'
cm1 = CustomizedMethods()
cm2 = CustomizedMethods()
print cm1.class_var1, cm1.class_var2 #'foo bar'
print cm2.class_var1, cm2.class_var2 #'foo bar'
cm2.class_var1, cm2.class_var2 = 'bar','for'
print cm1.class_var1, cm1.class_var2 #'foo bar' #here not changed as my expectation
print cm2.class_var1, cm2.class_var2 #'bar foo' #here has changed but they seemed to become instance variables.
我很困惑,因为我尝试的不同于Python的官方文档。
答案 0 :(得分:4)
在实例上分配属性时,它会在实例上分配,即使它以前存在于类中也是如此。起初,class_var1
和class_var2
确实是类属性。但是当您执行cm1.class_var1 = "bar"
时,您不会更改此类属性。相反,您正在创建一个新属性,也称为class_var1
,但这个属性是实例cm1
上的实例属性。
这是另一个显示差异的例子,虽然它仍然可能有点难以理解:
>>> class A(object):
... var = []
>>> a = A()
>>> a.var is A.var
True
>>> a.var = []
>>> a.var is A.var
False
首先,a.var is A.var
为真(即它们是同一个对象):因为a
没有自己的属性var
,所以试图访问班级。在为a
提供其自己的实例属性后,它将不再与该类的属性相同。
答案 1 :(得分:1)
您正在为实例分配属性,所以是的,它们在那时成为实例变量。 Python在你指定的任何对象上查找属性,然后如果在那里找不到它们,则查找继承链(对类,类的父类等)。因此,您在实例上指定的属性“阴影”或“隐藏”该类的同名属性。
答案 2 :(得分:0)
当您重新分配cm2
变量时,您创建了“隐藏”类变量的新实例变量。
>>> CustomizedMethods.class_var1 = 'one'
>>> CustomizedMethods.class_var2 = 'two'
>>> print cm1.class_var1, cm1.class_var2
one two
>>> print cm2.class_var1, cm2.class_var2
bar for
答案 3 :(得分:0)
字符串是不可变的,因此类和实例变量之间的差异并不明显。对于类定义中的不可变变量,要注意的主要是减少对内存的使用(即,如果你有1000个CustomizedMethods实例,那么仍然只有一个字符串“foo”存储在内存中。)
但是,如果你不知道自己在做什么,在类中使用可变变量会引入细微的错误。
考虑:
class CustomizedMethods(object):
class_var = {}
cm1 = CustomizedMethods()
cm2 = CustomizedMethods()
cm1.class_var['test'] = 'foo'
print cm2.class_var
'foo'
cm2.class_var['test'] = 'bar'
print cm1.class_var
'bar'
答案 4 :(得分:0)
尝试
print cm1.__dict__
print cm2.__dict__
它会很有启发......
当您向cm2询问属性时,它首先查看实例的属性(如果与名称匹配),然后在类属性中没有匹配属性时。
因此class_var1和class_var2是类属性的名称。
还要尝试以下方法:
cm2.__class__.class_var1 = "bar_foo"
print cm1.class_var1
你期待什么?