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

在python中,确保字典作为另一个类的构造函数中的参数传递的最佳方法/实践是什么?,python,dictionary,Python,Dictionary,假设有两个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.l

假设有两个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())似乎不是正确的方法。一定有更好的办法

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


有更好的办法吗?一定有

在Python中,没有类似于其他一些语言试图提供的私有或受保护数据。要真正保留原始数据,这是最好的选择,您只需付出在内存中复制数据的代价

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

>>> 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
中的可变对象,例如列表和dict,仍然可以修改

作为一种风格说明,大多数Python开发人员都不会试图对此进行防御性编程。相反,您只需信任文档(或RTF),了解库是否会对输入进行变异编写良好的库很少会作为副作用改变输入。一般而言,功能将:

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

在Python中,没有其他一些语言试图提供的私有或受保护数据的模拟。要真正保留原始数据,这是最好的选择,您只需付出在内存中复制数据的代价

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

>>> 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
中的可变对象,例如列表和dict,仍然可以修改

作为一种风格说明,大多数Python开发人员都不会试图对此进行防御性编程。相反,您只需信任文档(或RTF),了解库是否会对输入进行变异编写良好的库很少会作为副作用改变输入。一般而言,功能将:

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

函数不应改变任何输入参数,除非这是函数的唯一目的。构造函数不应该这样做。如果函数的目的是修改参数,而您不希望修改影响原始参数,那么
deepcopy()
是最好的解决方案。为什么你不认为这是正确的方法呢?一个简单的方法是,在字典中保留一个键,将mutated设置为false,并且每当更新字典时,确保将该键更新为true,因此,如果你想访问未更改的版本
deepcopy(),你只需验证字典是否发生了变化
实际上是正确的方法。要深入讨论为什么deepcopy是正确的方法(忽略库变异值的明显设计问题),请参阅此处的pep--@DishantArora:听起来您试图使用技术手段来防止团队中的其他人编写错误代码。这是一个崇高的目标,但Python语言并不是为了支持这一目标而设计的:在Python中,即使是关于私有对象成员的基本保护也只通过约定而不是任何语言特性来实施。Python采取的立场是,应该信任程序员理解他们使用的库,并编写没有bug的代码。这种信任是好是坏是有争议的,但不管是好是坏,Python就是这样。函数永远不应该改变任何输入参数,除非这是函数的唯一目的。构造函数不应该这样做。如果函数的目的是修改参数,而您不希望修改影响原始参数,那么
deepcopy()
是最好的解决方案。为什么你不认为这是正确的方法呢?一个简单的方法是,在字典中保留一个键,将mutated设置为false,并且每当更新字典时,确保将该键更新为true,因此,如果你想访问未更改的版本
deepcopy(),你只需验证字典是否发生了变化
实际上是正确的方法。要深入讨论为什么deepcopy是正确的方法(忽略库变异值的明显设计问题),请参阅此处的pep--@DishantArora:听起来您试图使用技术手段来防止团队中的其他人编写错误代码。这是一个崇高的目标,但Python语言并不是为了支持这一目标而设计的:在Python中,即使是关于私有对象成员的基本保护也只通过约定而不是任何语言特性来实施。Python采取的立场是,应该信任程序员理解他们使用的库,并编写没有bug的代码。这种信任是好是坏当然是有争议的,但不管是好是坏,Python就是这样。是的,我同意。应该是这样的。但我没有其他途径