确保在 python 中作为另一个类的构造函数中的参数传递的字典不被改变的最佳方法/实践是什么?

Dis*_*ora 3 python dictionary

假设有 2 个 python 模块 - Library 和 application 。

库代码:

class lib():

    def __init__(self,arg):
        smallArg = arg['key1']['key2']
        smallArg['key3'] = 2
Run Code Online (Sandbox Code Playgroud)

申请代码:

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()
Run Code Online (Sandbox Code Playgroud)

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

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

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

这只是两个模块相互作用的一个小例子。考虑更多的模块相互传递嵌套字典,计算它们并返回它们。任何模块都可以更改嵌套字典的结构。很有可能错过这个细节并可能破坏代码。

有没有更好的办法 ?必须有。

wim*_*wim 5

在 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
Run Code Online (Sandbox Code Playgroud)

然而,这仅适用于简单的情况:嵌套在 中的可变对象d(例如列表和字典)仍然可以修改。

作为风格说明,大多数 Python 开发人员不会尝试进行防御性编程。相反,您只需相信有关库是否会改变输入的文档(或 RTFS)。编写良好的库很少会产生副作用而改变输入。一般来说,函数将:

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