在python中确保作为变量传递给另一个类的构造函数的字典不发生突变的最佳方法/做法是什么?

时间:2018-11-01 16:37:20

标签: python dictionary

假设有2个python模块-库和应用程序。

库代码:

class lib():

    def __init__(self,arg):
        smallArg = arg['key1']['key2']
        smallArg['key3'] = 2

应用代码:

class app():

    def __init__(self):
        self.arg = {'key1' : {'key2' : {'key3' : 1}}}
        self.libObj = lib(self.arg)

    def getArg(self):
        print(self.arg)

appObj = app()
app.getArg()

由于字典是可变的,因此将打印由库代码更改的字典{'key1':{'key2':{'key3':2}}}。这意味着库甚至可以添加或删除更多键,应用程序也可以获取该突变字典。

有没有一种方法/做法可以真正确保其他模块不会干扰传递的字典的结构?

--->使用copy.deepcopy()或json.loads(json.dumps())似乎不是正确的方法。一定有更好的方法!

这只是一个小例子,其中2个模块相互交互。考虑另外几个将嵌套字典相互传递,计算并返回的模块,任何模块都可以更改嵌套字典的结构。很有可能会错过此细节,并且可能会破坏代码。

有更好的方法吗?必须有。

1 个答案:

答案 0 :(得分:3)

在Python中,没有其他某些语言试图提供的私有或受保护数据的类似物。要真正保留原始文档,copy.deepcopy是最佳选择,而您只需付出复制内存中数据的代价。

对于浅的键/值映射,可以通过在周围传递映射代理来避免复制:

>>> from types import MappingProxyType
>>> d = {'k': 'v'}
>>> d_readonly = MappingProxyType(d)
>>> d_readonly['k']
'v'
>>> d_readonly['k'] = 'spam'
TypeError: 'mappingproxy' object does not support item assignment

但是,这仅在简单情况下才有效:嵌套在d中的可变对象(如列表和字典)仍可以修改。

作为样式说明,大多数Python开发人员不会尝试对此进行防御性编程。取而代之的是,您将只相信有关库是否将使输入突变的文档(或RTFS)。 写得很好的库很少会改变输入的副作用。通常,函数可以:

  • 避免修改输入,并返回一个新对象(例如sorted),或
  • 就地修改输入,不返回任何内容(例如list.sort