我的问题看起来像这样。
# Module.py
class TestClass:
name = "default"
nameDict = {'name':"standard"}
def __init__(self, name):
self.name = name
self.nameDict['name'] = name
然后我打电话给另一个模块的字段。该类之前已启动,我在名称字段上调用如下:
Module.TestClass("newName")
# Inside another function
print(Module.TestClass.name)
print(Module.TestClass.nameDict['name'])
给出了:
default #name
newName #nameDict
我不明白为什么会有不同的价值观。有谁知道为什么会这样?
感谢您的时间。
答案 0 :(得分:3)
这是一个有趣的问题;还有很多事情要做。
Module.TestClass
是您在' Module.py'中定义的课程。使用Module.TestClass("newName")
,您正在创建该类的实例,但您不保存它。
执行print(Module.TestClass.name)
后,您需要打印name
Module.TestClass
属性的值,即类,不该类的实例。您之前提供实例的name
并未更改类' name
属性。
真正有趣的是print(Module.TestClass.nameDict['name'])
。即使您仍在访问类的nameDict
属性,但 受您之前创建的实例的影响。这是因为Python变量保存对象的引用。定义类时,您为类范围中的属性nameDict
分配了一个字典。 类 和所有类的实例指向完全相同的字典对象。所以,如果你在一个地方改变它,它在任何地方都会改变,因为它实际上是完全相同的dict 。
这是一个很好的方式来做你看起来像你想做的事情:
# Module.py
class TestClass(object):
def __init__(self, name='default'):
self.name = name
self.nameDict = {'name': name}
# other.py
testclass_instance = Module.TestClass("newName")
# Inside another function
print(testclass_instance.name) # newName
print(testclass_instance.nameDict['name']) # newName
答案 1 :(得分:2)
您看到的差异是因为 -
字符串是不可变的,而字典是可变的。
在你的init函数中,当你这样做时 - self.name = name - 这会在你的实例中为name指定一个新的引用,它不会改变类变量名所持有的引用。
在init函数中,当你更改字典中name键的值时,你正在改变字典(这是类变量的同一个字典),因此它在类变量字典中反映为好。如果您在此处指定了新词典,则可以在类变量中看到旧值。
这基本上是因为当你创建一个实例时,类变量的引用会被复制到实例中,引用仍指向那时指向的任何类变量。因为在这种情况下,由于引用相同,所以对dict的更改反映在类变量中。
但是当你进行赋值时,你将变量指向一个新的引用,这不会导致类变量发生变化。
一个简单的例子来展示这个 -
>>> class CA:
... d = [1,2]
...
>>> CA.d
[1, 2]
>>> c = CA()
>>> c.d
[1, 2]
>>> id(c.d) == id(CA.d)
True
>>> c.d.append(3)
>>> CA.d
[1, 2, 3]
>>> c.d = [1,2,3,4,5]
>>> CA.d
[1, 2, 3]
>>> CA.d = [1,2,3,4,5,6]
>>> CA.d
[1, 2, 3, 4, 5, 6]
>>> d = CA()
>>> d.d
[1, 2, 3, 4, 5, 6]
>>> c.d
[1, 2, 3, 4, 5]
答案 2 :(得分:1)
这种行为对我来说也很令人惊讶:
import Module
# Inside another function
print(Module.TestClass.name) #<-- default
print(Module.TestClass.nameDict['name']) #<-- standard
foo = Module.TestClass("newName")
print(Module.TestClass.name) #<-- default
print(Module.TestClass.nameDict['name']) #<-- newName
为什么要问类变量?也许你想做:
foo = Module.TestClass("newName")
print(foo.name)
print(foo.nameDict['name'])
答案 3 :(得分:1)
这是因为TestClass.name
是一个字符串对象,因此是不可变的,而TestClass.nameDict
是一个可变的字典对象。因此,当您执行self.name = name
时,会在实例上使用&#39; newName&#39;创建新的名称变量。值,当你执行self.nameDict['name'] = name
时,dict类变量会发生变异。
要验证此行为,您可以检查变量的ID:
实施例: -
class TestClass(object):
...
def __init__(self, newName):
print(id(self.name)) #1
self.name = newName
print(id(self.name)) #2
print(id(self.nameDict)) #3
self.nameDict['name'] = newName
print(id(self.nameDict)) #4
供进一步参考: - Mutable and immutable objects in python