首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >私下更新字典?

私下更新字典?
EN

Stack Overflow用户
提问于 2019-05-27 04:12:05
回答 2查看 57关注 0票数 -2

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

假设字典是这样的:

代码语言:javascript
复制
my_attributes = {"test": True}

和一些类似这样的逻辑:

代码语言:javascript
复制
class MyClass(object):

    def __init__(self, attributes):
        if my_condition():
            attributes.update({"test": False})

最终结果:

代码语言:javascript
复制
>>> my_attributes
{'test': False}

因此,下次使用MyClass时,这些根属性仍然会被覆盖。

我似乎已经通过重新定义attributes绕过了这个问题

代码语言:javascript
复制
class MyClass(object):

    def __init__(self, attributes):
        if my_condition():
            attributes = {}
            attributes.update(my_attributes)
            attributes.update({"test": False})

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-27 04:22:00

如下所示:

代码语言:javascript
复制
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)

输出:

代码语言:javascript
复制
my_attributes: {'test': True} class.attributes: {'test': False}
票数 0
EN

Stack Overflow用户

发布于 2019-05-27 05:18:32

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

代码语言:javascript
复制
>>> 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提供不可变的引用。副本就是我们要走的路:

代码语言:javascript
复制
>>> d = {}
>>> L = ctor(dict(d)) # I don't give you *my* d
>>> d[1] = 2
>>> L
[{}]

如果我是对象,我会在使用它之前复制一个对象:

代码语言:javascript
复制
>>> 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

但是现在你已经制作了对象的两个副本,因为每个人都害怕看到它的变量被另一个修改了。如果字典包含(可变的)引用,问题仍然存在。

解决方案是详细说明每个人的职责:

代码语言:javascript
复制
class MyClass(object):
    """Usage: MyClass(attributes).do_something() where attributes is a mapping.
    The mapping won't be modified"""
    ...

请注意,这是常见的预期行为:除非指定,否则函数/构造器的参数不会被修改。我们尽可能避免副作用,但情况并不总是这样:参见list.sort()sorted(...)

因此,我认为您的解决方案很好。但我倾向于避免在构造函数中使用过多的逻辑:

代码语言:javascript
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56317027

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档