我正在学习此内容,这是为了了解类属性。但是与以下代码段的输出混淆了。
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
和输出是
0set([0, 1])
1set([1, 2])
2set([2, 3])
0set([0, 1])
1set([1, 2])
2set([2, 3])
我期待这样的输出。
0set([2, 3])
1set([2, 3])
2set([2, 3])
0set([])
1set([])
2set([])
而解释是,当我们写self.aliases = set([])
我们实际上是在创建一个新的实例属性,遮蔽类属性。
因此,如果我们使__init__
函数如下所示,我们将获得预期的输出。
def __init__(self,name):
self.name = name
A.aliases = set([name]) #using the class attribute directly
还请考虑以下代码段:
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)
由于在这种情况下,我们没有创建实例属性,所以没有阴影。问题中的测试代码将产生以下输出:
0set([0, 1, 2, 3])
1set([0, 1, 2, 3])
2set([0, 1, 2, 3])
0set([])
1set([])
2set([])
这是预期的,因为在所有实例之间共享类属性。
这里A.alias
也可以称为self.alias
内部init
函数或任何其他函数。并且由于它没有遮盖静态属性,因此提供了预期的输出-所有对象共享一个公共属性的情况。
一个人不知道这个概念的同时,将使用类似一成不变的数据结构不通知任何东西string
等,但像数据结构的情况下,list
与dictionary
此可能会感到惊讶。
还要考虑以下的定义init
。
def __init__(self,name):
self.name = name
self.aliases.add(name) # referring to class attribute
self.aliases = set([]) # creating a instance attribute
而且在这种情况下,它最终instance attribute
通过测试代码创建和产生的输出是:
0set([1])
1set([2])
2set([3])
0set([1])
1set([2])
2set([3])
因此,我的学习是:
始终用类名引用类属性,用对象名引用实例属性,即A.aliases
在您指类属性时写aliases
,不要写self.aliases
间接引用self.aliases
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句