gpt4 book ai didi

python - 派生类中来自父级的成员会干扰,具体取决于初始化

转载 作者:行者123 更新时间:2023-12-04 07:43:34 25 4
gpt4 key购买 nike

为什么是 letters在下面的子实例之间共享?

class Parent:
letters = list()

def add(self, letter):
self.letters.append(letter)

class A(Parent):
def add_a(self):
self.add('a')

class B(Parent):
def add_b(self):
self.add('b')

a = A()
b = B()

a.add_a()
b.add_b()

print(a.letters)
# a.letters now contains a renegade b!
如果我重新定义 Parent像这样
class Parent:
def __init__(self):
self.letters = list()

def add(self, letter):
self.letters.append(letter)
abletters 的单独列表.这是我对第一个代码的期望。有什么不同?

最佳答案

初学者非常频繁的错误 - 我自己做了几个月。 letters分配/绑定(bind)到 class Parents .任何查看和修改它的人都是在 letters 的单个副本上这样做的。 ,它是共享的(您可以使用 print(f"{id(self.letters)=}") 查看变量的内存分配标识符)。
继承与它无关,如果您创建 3 个类中的任何一个的 5 个实例并开始添加字母,您将获得相同的效果。发生的事情是 letters是可变类型,修改它会愉快地修改每个人共享的副本,即使 self.letters使它看起来像一个私有(private)副本。
在第二种情况下,您创建一个新的 letters对于每个新实例。这很可能是您想要的。通过创建一个新的 letters在每个实例上,您都避免了不必要的共享。
如果您添加到数字或连接到字符串,则此行为会有所不同 - 这些是不可变类型,因此每个实例都会修改自己的本地副本,即使它首先开始查看 Parent。 (基本上,它读取共享副本,但它将任何修改的结果分配给绑定(bind)到同名 self 命名空间的该变量的副本)。
另见 "Least Astonishment" and the Mutable Default Argument
哦,还有关于 print(id(var)) 的技巧?不要依赖它对 255 以下的整数做同样的事情——Python 通过只保存所有此类变量的 1 个副本来优化事物。 2在 5 个不同的变量中都有相同的 id6在另外 4 个景点分享了另一个独特的 id .

关于python - 派生类中来自父级的成员会干扰,具体取决于初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67319929/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com