Python对词典很奇怪

时间:2013-08-30 23:21:00

标签: python

当我执行这个python代码时,它会生成下面的输出。

class A(object):
    a = 0
    n = {}

    def inc(self):
        self.a += 1

    def add(self, key, obj):
        self.n[key] = obj

    def printn(self):
        print self.a
        print self.n


b = A()
c = A()

b.add("asf", "----")
c.add("asdf", "====")

b.inc()
c.inc()

b.printn()
c.printn()

输出:

1
{'asf': '----', 'asdf': '===='}
1
{'asf': '----', 'asdf': '===='}

2 个答案:

答案 0 :(得分:5)

问题与n是字典无关;这是n是一个类属性而不是实例属性。这意味着该类的所有实例共享一个值。

解决方案只是将其转换为实例变量 - 将其分配到方法(通常是__init__方法)中,而不是在类定义中。

class A(object):
    def __init__(self):
        self.n = {}

您可能会问为什么a不会发生同样的事情。嗯, 。您正在创建一个共享a,就像n一样。

但是你没有在共享a上调用任何改变它的方法(事实上,你不能,因为int是不可变的;它没有任何改变它的方法)。使用n时,self.n[key] = object可能看起来不像是一个方法调用(实际上是self.n.__setitem__(key, object)),但显而易见的是它正在更改n的值,这是关键在这里。

您只是为self.a分配了一个新值。这会创建一个新的实例属性,该属性会隐藏同名的class属性 - 这会让人感到困惑,但它可以按照您的意愿运行。如果只想构建新值并将其分配给n,则可以使用self.n获得相同的行为:

def add(self, key, obj):
    new_n = copy.copy(n)
    new_n[key] = obj
    self.n = new_n

答案 1 :(得分:0)

n = {}

这不会像其他语言那样做。在其他语言中,您可能希望这声明一个始终使用空dict初始化的实例属性。在Python中,它创建了一个类属性。所有实例共享相同的n

要解决此问题,请编写构造函数并在self上设置属性:

def __init__(self):
    self.a = 0
    self.n = {}