为了账号安全,请及时绑定邮箱和手机立即绑定

意外的Python类变量

意外的Python类变量

ABOUTYOU 2022-06-28 11:05:09
我在 Python 中遇到过几次这种行为,这有点令人费解。class MyClass:    def __init__(self, initial_data={}):        self.data = initial_datainstance_a = MyClass()instance_a.data['key1'] = 'val1'print("instance_a.data:", instance_a.data)instance_b = MyClass()print("instance_b.data:", instance_b.data)输出:instance_a.data: {'key1': 'val1'}instance_b.data: {'key1': 'val1'}我希望data充当一个实例变量,但在这种情况下它看起来像一个类变量。有谁知道为什么会发生这种情况以及避免它的最佳做法是什么?
查看完整描述

2 回答

?
Cats萌萌

TA贡献1805条经验 获得超9个赞

分配时self.data = initial_data,您只需为对象创建另一个新名称initial_data。


您在这里没想到的行为是由于默认参数initial_data仅在声明方法时才被评估一次,而不是每次调用它时,所以所有使用它的实例实际上都使用相同的initial_datadict 对象,您可以以不同的名称访问,例如instance_a.data,instance_b.data等等。


经典的解决方案是None默认使用,如下所示:


class MyClass:

    def __init__(self, initial_data=None):

        if initial_data is None:

            initial_data = {}

        self.data = initial_data


查看完整回答
反对 回复 2022-06-28
?
UYOU

TA贡献1878条经验 获得超4个赞

因为数据变量的id是一样的。Python 中的函数是一流的对象,而不仅仅是一段代码。


print(id(instance_a.data))

# prints of object id


print(id(instance_b.data))

# prints the same object id

这是因为构造函数的参数中的固定值。它不会为每个对象创建一个新字典。


在这样做时:


def __init__(self):

    self.data = {}

你会得到不同的结果。


在这里阅读更多:http: //effbot.org/zone/default-values.htm


希望这有帮助,祝你好运。


查看完整回答
反对 回复 2022-06-28
  • 2 回答
  • 0 关注
  • 147 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信