简体   繁体   中英

What is the best way/practice to ensure in python that the dictionary passed as an argument in the constructor of another class, is not mutated?

Suppose there are 2 python modules - Library and application .

Library code :

class lib():

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

Application code :

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()

since dictionaries are mutable , this prints the dictionary {'key1' : {'key2' : {'key3' : 2}}} which was changed by library code. This means library could even add more keys or delete them , and application would also get that mutated dictionary.

is there a way/practice to really ensure that the other modules don't disturb the structure of the dictionary passed ??

---> using copy.deepcopy() or json.loads(json.dumps()) doesn't seem the right way. There must be a better way !

This is just a small example where 2 modules interact with each other. Think about several more modules passing nested dictionaries to each other , computing them and returning them.Any module can change the structure of the nested dictionary. There is a good chance of missing out this detail and might break the code.

Is there a better way ? There must be.

In Python, there is no analogue of private or protected data that some other languages attempt to provide. To really preserve the original, copy.deepcopy would be the best choice, and you just pay the price of copying the data in memory.

For a shallow map of key/vals, you could avoid a copy by passing a mapping proxy around:

>>> 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

However, this only really works for simple cases: mutable objects nested within d , such as lists and dicts, could still be modified.

As a style note, most Python developers do not try to program this defensively. Instead, you would just trust the documentation (or RTFS) about whether a library will or will not mutate an input. Well written libraries will seldom mutate inputs as a side-effect . Generally, functions will either:

  • Avoid modifying inputs, and return a new object (eg sorted ), or
  • Modify the input in-place, and not return anything (eg list.sort )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM