Python 私下更新字典?

Python 私下更新字典?,python,Python,我有一个类对象,它接收一些数据。基于某个条件,我需要更改该数据,但仅在该条件下。我遇到的问题是,当我调用dict.update时,它也会更新原始变量。所以随后的请求进入,现在可以说原始变量被污染了,并且使用了它不应该拥有的重写信息 假设字典是这样的: my_attributes = {"test": True} class MyClass(object): def __init__(self, attributes): if my_condition():

我有一个类对象,它接收一些数据。基于某个条件,我需要更改该数据,但仅在该条件下。我遇到的问题是,当我调用dict.update时,它也会更新原始变量。所以随后的请求进入,现在可以说原始变量被污染了,并且使用了它不应该拥有的重写信息

假设字典是这样的:

my_attributes = {"test": True}
class MyClass(object):

    def __init__(self, attributes):
        if my_condition():
            attributes.update({"test": False})
class MyClass(object):
    @staticmethod
    def my_condition():
        return True

    def __init__(self, attributes):
        self.attributes = {**attributes}
        if MyClass.my_condition():
            self.attributes["test"] = False


my_attributes = {"test": True}
cls_obj = MyClass(my_attributes)
print("my_attributes:", my_attributes, "class.attributes:", cls_obj.attributes)
有些逻辑是这样的:

my_attributes = {"test": True}
class MyClass(object):

    def __init__(self, attributes):
        if my_condition():
            attributes.update({"test": False})
class MyClass(object):
    @staticmethod
    def my_condition():
        return True

    def __init__(self, attributes):
        self.attributes = {**attributes}
        if MyClass.my_condition():
            self.attributes["test"] = False


my_attributes = {"test": True}
cls_obj = MyClass(my_attributes)
print("my_attributes:", my_attributes, "class.attributes:", cls_obj.attributes)
最终结果是:

>>> my_attributes
{'test': False}
因此,下次使用MyClass时,这些根属性仍然被覆盖

我似乎通过重新定义属性解决了这个问题:

这似乎解决了问题,但我不完全确定这是一个好的,甚至是正确的解决方案

类似这样:

my_attributes = {"test": True}
class MyClass(object):

    def __init__(self, attributes):
        if my_condition():
            attributes.update({"test": False})
class MyClass(object):
    @staticmethod
    def my_condition():
        return True

    def __init__(self, attributes):
        self.attributes = {**attributes}
        if MyClass.my_condition():
            self.attributes["test"] = False


my_attributes = {"test": True}
cls_obj = MyClass(my_attributes)
print("my_attributes:", my_attributes, "class.attributes:", cls_obj.attributes)
输出:

my_attributes: {'test': True} class.attributes: {'test': False}

将可变字典引用传递给对象。现在,您有了引用的两个所有者:构造函数的调用者对象的外部世界和对象本身。这两个所有者可以修改字典。下面是一个例子:

>>> d = {}
>>> def ctor(d): return [d] # just build a list with one element
>>> L = ctor(d)
>>> d[1] = 2
>>> L
[{1: 2}]
>>> L[0][3] = 4
>>> d
{1: 2, 3: 4}
你如何预防这种情况?两个所有者都希望保护自己不受其变量的野生变异的影响。如果我是外部世界,我希望传递dict的不可变引用,但是Python不为dict提供不可变引用。复制是一种方式:

>>> d = {}
>>> L = ctor(dict(d)) # I don't give you *my* d
>>> d[1] = 2
>>> L
[{}]
如果我是对象,我会在使用前复制对象:

>>> d = {}
>>> def ctor2(d): return [dict(d)] # to be sure L[0] is *mine*!
>>> L = ctor2(dict(d)) # I don't give you *my* d
但是现在你已经复制了两个对象,只是因为每个人都害怕看到它的变量被另一个修改。如果字典中包含可变引用,那么问题仍然存在

解决方案是明确每个人的责任:

class MyClass(object):
    """Usage: MyClass(attributes).do_something() where attributes is a mapping.
    The mapping won't be modified"""
    ...
请注意,这是常见的预期行为:除非指定,否则不会修改函数/构造函数的参数。我们尽可能避免副作用,但情况并非总是如此:请参阅list.sort vs sorted

因此,我认为你的解决方案是好的。但我更喜欢避免构造函数中有太多逻辑:

class MyClass(object):
    @staticmethod
    def create_prod(attributes):
        attributes = dict(attributes)
        attributes.update({"test": False})
        return MyClass(attributes)

    @staticmethod
    def create_test(attributes):
        return MyClass(attributes)

    def __init__(self, attributes):
        self._attributes = attributes # MyClass won't modify attributes

你需要复制一份数据。请参阅copy.copy或copy.deepcopy.attributes作为参考。如果要复制dict,请使用priv_attributes={**attributes}attributes=dictmy_attributes创建浅层克隆,如果需要deepcopy,则需要自己编写:D attributes['test']=false您正在更新传递给构造函数的对象,因此该对象当然会更新。很可能,您想复制该对象,但考虑到您的代码,我不确定这一点是什么,因为您会放弃它,也不完全确定为什么我的问题会被否决。我认为这是一个关于对python的误解的非常详细的问题。谢谢大家的帮助。