【发布时间】:2017-12-30 06:58:02
【问题描述】:
下面的代码让我很困扰:-
class mytest:
name="test1"
tricks=list()
def __init__(self,name):
self.name=name
#self.tricks=[name]
self.tricks.append(name)
t1=mytest("hello world")
t2=mytest("bye world")
print t1.name,t2.name
print t1.tricks,t2.tricks
输出是:-
hello world bye world
['hello world', 'bye world'] ['hello world', 'bye world']
意思是列表tricks被t1和t2这两个实例共享,在https://docs.python.org/3/tutorial/classes.html的9.3.5小节已经解释过
但是,如果我执行以下代码:-
class mytest:
name="test1"
tricks=list()
def __init__(self,name):
self.name=name
self.tricks=[name]
self.tricks.append(name)
t1=mytest("hello world")
t2=mytest("bye world")
x=t1.tricks
if type(x) is list:
print 'a list'
elif type(x) is tuple:
print 'a tuple'
else:
print 'neither a tuple or a list'
print t1.name,t2.name
print t1.tricks,t2.tricks
输出如下:-
a list
hello world bye world
['hello world', 'hello world'] ['bye world', 'bye world']
现在看来,列表tricks 不再由这两个实例 t1 和 t2 共享。
我的问题是,这里的机制是什么?
【问题讨论】:
-
第二种情况与类属性无关。它是底层对象。每次调用
__init__都会创建一个新的列表对象:[name]。因此,每个实例的属性tricks所引用的列表是独立的。 -
@MosesKoledoye 而新创建的列表
[name]覆盖了旧列表tricks?那么旧对象tricks被删除了吗? -
如果你写
self.tricks = [name],那么self会收到一个属性tricks,它会影响类成员myclass.tricks。 -
第二个代码创建了一个实例属性
self.tricks,它隐藏了类属性mytest.tricks。所以如果你想在第二个代码中访问mytest.tricks,你需要使用mytest.tricks这个名字。 -
您可能希望遵守class naming conventions,即使是玩具示例,也只是为了练习。