Difference between MappingProxyType and PEP 416 frozendict

While frozendict was rejected , the associated types.MappingProxyType class was added to the public API in python 3.3.

I understand that MappingProxyType is just a wrapper around the base dict , but despite this, is it functionally not equivalent to frozendict ?

In other words, what is the significant difference between the original PEP 416 frozendict and this:

 from types import MappingProxyType def frozendict(*args, **kwargs): return MappingProxyType(dict(*args, **kwargs)) 

Of course, MappingProxyType not hashed as is, but as suggested by PEP for frozendict , it can be made hashable after ensuring that all its values ​​are hashed (MappingProxyType cannot be subclassed, so compilation and transfer of methods will be required for this).

+10
source share
2 answers

TL DR

MappingProxyType is a read-only proxy for displaying (for example, dict) objects.

frozendict - an unchanging dictate

Answer

Proxy template (quote from Wikipedia ):

A proxy, in its most general form, is a class that functions as an interface to something else.

MappingProxyType is just a simple proxy (i.e. an interface) for accessing a real object (a real map, which in our example is a dict).

the proposed frozendict object frozendict exactly the same as for Frozenset. a read-only (immutable) object that can only be modified after creation.

So why do we need MappingProxyType ? An example of use is when you want to pass a dictionary to another function, but without the ability to change your dictionary, it acts as a read-only proxy (quoting Python documents ):

Read-only proxy display. This provides a dynamic look at the records of the mappings, which means that when the mappings change, the view reflects these changes.

Let's look at an example using MappingProxyType

 In [1]: from types import MappingProxyType In [2]: d = {'a': 1, 'b': 2} In [3]: m = MappingProxyType(d) In [4]: m['a'] Out[4]: 1 In [5]: m['a'] = 5 TypeError: 'mappingproxy' object does not support item assignment In [6]: d['a'] = 42 In [7]: m['a'] Out[7]: 42 In [8]: for i in m.items(): ...: print(i) ('a', 42) ('b', 2) 

Update:

since PEP has not turned into python, we cannot know exactly what the implementation will be. looking at PEP, we will see that:

 frozendict({'a': {'b': 1}}) 

will throw an exception because {'b': 1} not a hash value, but in your implementation it will create an object. Of course, you can add validation of the value as indicated in PEP.

I assume that memory optimization was part of PEP, and an implementation of this kind of frozendict could benefit from dict comparison performance using the __hash__ implementation.

+7
source

One thing I noticed is that frozendict.copy supports add / replace (limited to string keys), while MappingProxyType.copy does not. For instance:

 d = {'a': 1, 'b': 2} from frozendict import frozendict fd = frozendict(d) fd2 = fd.copy(b=3, c=5) from types import MappingProxyType mp = MappingProxyType(d) # mp2 = mp.copy(b=3, c=5) => TypeError: copy() takes no keyword arguments # to do that w/ MappingProxyType we need more biolerplate temp = dict(mp) temp.update(b=3, c=5) mp2 = MappingProxyType(temp) 

Note. None of these two immutable cards support the "delete and return a new immutable copy" operation.

0
source

Source: https://habr.com/ru/post/1263174/


All Articles