Python object list weird behaviour
我刚刚开始学习Python,来自Java/C++背景,发现下面的行为有点混乱。在调用s.add ou trick("woof")和d.add ou trick("woof")之后,s.tricks和d.tricks都包含["woof"、"bark"]。但是,调用方()的行为不同。有人能解释吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class PartyAnimal:
x = 0
name = ''
tricks = []
def __init__(self, name):
self.name = name
def party(self):
self.x += 1
def add_trick(self, trick):
self.tricks.append(trick)
s = PartyAnimal("Sally")
d = PartyAnimal("Danny")
s.party()
d.party()
s.add_trick("Woof")
d.add_trick("Bark")
print 's', s.name, s.x, s.tricks
print 'd', d.name, d.x, d.tricks |
输出是这样的:
1 2
| s Sally 1 ['Woof', 'Bark']
d Danny 1 ['Woof', 'Bark'] |
- tricks是一个类实例,因此每个PartyAnimal()实例只共享一个副本。
- 在C++中,您的变量x、name和tricks将是static,也就是说,您的类中的所有实例都共享这些变量。要使它们特定于类的一个实例,只需将它们分配给self。
- 这在dupe目标中有介绍,但是一个重要的区别是self.tricks.append(trick)修改了现有的tricks类属性,但是self.x += 1不修改x类属性,因为您正在执行一个赋值。相反,它创建一个x实例属性(它隐藏了相同名称的类属性)来保存新的整数对象。
- (续)如果您执行self.tricks = self.tricks + [trick],这也将创建一个tricks实例属性,尽管使用+=不会,但它只会改变类属性,就像.append方法那样。整数上的+=不能改变整数,因为python整数是不可变的。
您正在创建一个由类的所有实例共享的tricks列表。在__init__中创建一个新列表,而不是:
1 2 3
| def __init__(self, name):
self.name = name
self.tricks = [] |
- 虽然不相关,但在C级还是Java中,将EDOCX1的0个级别放在课堂上是一个好的做法吗?
- @不,因为这在语义上不同于让每个实例都有自己的列表。把这个列表放在类级别就像用C风格的语言把它变成static。
- 为什么更改s.name或s.x的行为与附加到列表的行为不同?
- 如果它是一个类变量,它完全可以,类似于爪哇/C中的EDCOX1×1的成员变量。
- @dannyliu因为您没有改变这个整数或字符串,所以您将x或name属性设置为指向另一个对象。
- 假设tricks = []更像静态的,那么在没有初始化时,self.tricks.append如何工作?
- 该行self.tricks = []将创建一个新列表[]并将self的属性tricks指向该列表。
- @沙哈卡佩斯:以东十一〔7〕是以东十一〔12〕的捷径。它已初始化。
- 同意。原始问题中的self.tricks = []在哪里?
- @无处可寻。在我的答案里。
- @Anttihaapala:虽然我可以运行原始问题的代码,但我不明白如果tricks = []是一个类级变量,self.tricks.append是如何工作的?:)
- @Shahkalpesh从来没有太多的声誉来开始阅读python 3教程
- 同样适用于@dannyliu,您的示例在这里解释得很好。^
- @安提哈帕拉明白了。C背景下,我认为Python中的EDOCX1 10是E/OCX1,17在C/JAVA中。因此,不能引用EDCOX1×17来引用类级变量(EcOXX1,1,C,C/Java)。谢谢您。我今天学到了一些新东西。