Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between MappingProxyType and PEP 416 frozendict

Tags:

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

I understand MappingProxyType is just a wrapper around the underlying dict, but despite that isn't it functionally equivalent to frozendict?

In other words, what's the substantive 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 is not hashable as is, but just as the PEP suggested for frozendict, it can be made hashable after ensuring that all its values are hashable (MappingProxyType cannot be subclassed, so it would be require composition and forwarding of methods).

like image 783
max Avatar asked Jan 22 '17 19:01

max


People also ask

What is MappingProxyType?

The MappingProxyType is just a simple proxy (i.e. interface) to access the real object (the real map, which on our example is dict). the suggested frozendict object is just as set is to frozenset. a read only (immutable) object which can only be changed upon creation.

How do you make a dictionary immutable in Python?

I would just override the __setitem__() method of your dict. Note however, that this doesn't guarantee that the values of your dict will be immutable (say you have values that are lists, for example).


2 Answers

TL;DR

MappingProxyType is a read only proxy for mapping (e.g. dict) objects.

frozendict is an immutable dict

Answer

The proxy pattern is (quoting wikipedia):

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

The MappingProxyType is just a simple proxy (i.e. interface) to access the real object (the real map, which on our example is dict).

the suggested frozendict object is just as set is to frozenset. a read only (immutable) object which can only be changed upon creation.

So why do we need MappingProxyType? example use case is where you want to pass a dictionary to another function but without it able to change your dictionary, it act as a read only proxy, (quoting python docs):

Read-only proxy of a mapping. It provides a dynamic view on the mapping’s entries, which means that when the mapping changes, the view reflects these changes.

lets see some example usage of the 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:

because the PEP did not make it into python, we cannot know for sure what the implementation that would be. by looking at the PEP we see that:

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

would raise an exception as {'b': 1} is not hashable value, but on your implementation it will create the object. of-course, you can add a validation for the value as noted on the PEP.

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

like image 68
ShmulikA Avatar answered Sep 25 '22 07:09

ShmulikA


MappingProxyType add immutability only on a first level:

>>> from types import MappingProxyType >>> d = {'a': {'b': 1}} >>> md = MappingProxyType(d) >>> md mappingproxy({'a': {'b': 1}}) >>> md['a']['b'] 1 >>> md['a']['b'] = 3 >>> md['a']['b'] 3 
like image 34
Alexey Shrub Avatar answered Sep 25 '22 07:09

Alexey Shrub