访问字段:如果存储在字典

时间:2015-08-10 08:16:10

标签: python dictionary scope

我的问题看起来像这样。

# 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

我不明白为什么会有不同的价值观。有谁知道为什么会这样?

感谢您的时间。

4 个答案:

答案 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)

您看到的差异是因为 -

  1. 字符串是不可变的,而字典是可变的。

  2. 在你的init函数中,当你这样做时 - self.name = name - 这会在你的实例中为name指定一个新的引用,它不会改变类变量名所持有的引用。

  3. 在init函数中,当你更改字典中name键的值时,你正在改变字典(这是类变量的同一个字典),因此它在类变量字典中反映为好。如果您在此处指定了新词典,则可以在类变量中看到旧值。

  4. 这基本上是因为当你创建一个实例时,类变量的引用会被复制到实例中,引用仍指向那时指向的任何类变量。因为在这种情况下,由于引用相同,所以对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

1与#2不同,而#3和#4则相同。

供进一步参考: - Mutable and immutable objects in python