Class attribute shadowing in Python class
本问题已经有最佳答案,请猛点这里访问。
我学习这个和这个是为了理解课堂属性。但对以下代码片段的输出感到困惑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class A: aliases = None name = None def __init__(self,name): self.name = name self.aliases = set([name]) def add_aliases(self,a): self.aliases.add(a) def __repr__(self): return str(self.name) + str(self.aliases) arr = [] for i in range(3): arr.append(A(i)) arr[-1].add_aliases(i+1) for item in arr: print item A.aliases = set([]) ##Modify the static element of class for item in arr: print item |
python解释器:2.7.9
输出是
1 2 3 4 5 6 | 0set([0, 1]) 1set([1, 2]) 2set([2, 3]) 0set([0, 1]) 1set([1, 2]) 2set([2, 3]) |
我期待这样的结果。
1 2 3 4 5 6 | 0set([2, 3]) 1set([2, 3]) 2set([2, 3]) 0set([]) 1set([]) 2set([]) |
解释是,当我们编写
因此,如果我们使我们的
1 2 3 | def __init__(self,name): self.name = name A.aliases = set([name]) #using the class attribute directly |
还要考虑以下代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class A: aliases = set([]) name = None def __init__(self,name): self.name = name self.aliases.add(name) # using the class attribute indirectly. def add_aliases(self,a): self.aliases.add(a) def __repr__(self): return str(self.name) + str(self.aliases) |
因为在本例中,我们不创建实例属性,所以没有阴影。而问题中的测试代码将产生以下输出:
1 2 3 4 5 6 | 0set([0, 1, 2, 3]) 1set([0, 1, 2, 3]) 2set([0, 1, 2, 3]) 0set([]) 1set([]) 2set([]) |
这是预期的,因为类属性在所有实例之间共享。
在这里,
不了解这一概念的人在使用不可变数据结构(如
还应考虑以下对
1 2 3 4 | def __init__(self,name): self.name = name self.aliases.add(name) # referring to class attribute self.aliases = set([]) # creating a instance attribute |
在这个例子中,它最终创建了
1 2 3 4 5 6 | 0set([1]) 1set([2]) 2set([3]) 0set([1]) 1set([2]) 2set([3]) |
从这一切我学到:
总是引用类名为的类属性和对象名为的实例属性,即写