为什么当我创建一个带有列表的类时,列表及其内容将变为全局
class A:
my_list = []
string = ""
def add(self, data):
self.string += "a"
self.my_list.append(data)
def print_list(self):
print(self.string)
print(self.my_list)
a = A()
b = A()
a.add("test")
a.print_list()
b.print_list()
a和b都将打印由a.add
创建的列表# results of a.print_list
xa
['test']
# results of b.print_list
x
['test']
所以我的问题是,这对python3来说是正常的,还是一个bug。 对我来说,似乎只有全局修改了列表。
答案 0 :(得分:1)
字符串是不可变的,所以
self.string += "a"
创建一个新对象并将其绑定到self.string
这显然是在改变列表
self.my_list.append(data)
也许更有趣的是
self.my_list += [data]
也会改变列表
一般规则是__iadd__
对可变对象和不可变对象的行为不同
答案 1 :(得分:1)
这是解释:
对象具有个性,多个名称(在多个范围内)可以绑定到同一个对象。这在其他语言中称为别名。乍一看Python时通常不会理解这一点,在处理不可变的基本类型(数字,字符串,元组)时可以安全地忽略它。但是,别名对包含可变对象(如列表,字典和大多数其他类型)的Python代码的语义可能会产生惊人的影响。这通常用于程序的好处,因为别名在某些方面表现得像指针。例如,传递一个对象很便宜,因为实现只传递一个指针;如果函数修改了作为参数传递的对象,调用者将看到更改 - 这消除了对Pascal中两个不同的参数传递机制的需要。
这就是解决方案:
(...)使用实例变量代替(...)
像这样:
class Dog:
def __init__(self, name):
self.name = name
self.tricks = [] # creates a new empty list for each dog
def add_trick(self, trick):
self.tricks.append(trick)
上述代码的结果:
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over')
>>> e.add_trick('play dead')
>>> d.tricks ['roll over']
>>> e.tricks ['play dead']
在您的示例中,您应该将my_list = []
声明移至init函数...
class A:
string = ""
def __init__(self):
self.my_list = []
def add(self, data):
self.string += "a"
self.my_list.append(data)
def print_list(self):
print(self.string)
print(self.my_list)
a = A()
b = A()
a.add("test")
a.print_list()
b.print_list()
希望得到这个帮助。
此致