[Tutor] FrozenDict
Albert-Jan Roskam
sjeik_appie at hotmail.com
Wed Oct 7 21:32:31 CEST 2015
> From: sjeik_appie at hotmail.com
> To: tutor at python.org
> Date: Wed, 7 Oct 2015 16:10:20 +0000
> Subject: [Tutor] FrozenDict
>
> Hi,
> I wanted to create a read-only dict to hold some constants. I looked around on the internet and created two implementations:-FrozenDict (derives from collections.mapping)-ChillyDict (derives from dict, which seems more obvious to me)
> The code can be found here: http://pastebin.com/QJ3V2mSK
> Some questions:1. one doctest from FrozenDict fails: fd.keys() returns an empty list. Why?
ok, the correct way to write __iter__ appears to be:
def __iter__(self):
return iter(self.__kwargs)
Now at least all doctests pass.
2. Is FrozenDict the way to use collections.mapping (aside from the error!). I just discovered this and i seems quite cool (pun intended)3. Which implementation is better, and why? I like ChillyDict better because it is more straightforward and shorter.
> The read-only dict does not need to be very fast, it just needs to give some reasonable protection against mutating values.It also needs to work under Python 2.7 and 3.3+.
> Thank you!
> Albert-Jan
Just in case, I am also pasting the code here, with the slightly modified__iter__:
from collections import Mapping
class FrozenDict(Mapping):
"""A dictionary that does not support item assignment after initialization
>>> fd = FrozenDict(a=1, b=2)
>>> fd["a"]
1
>>> fd["a"] = 777 # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
TypeError: 'FrozenDict' object does not support item assignment
>>> sorted(fd.items())
[('a', 1), ('b', 2)]
>>> sorted(fd.keys())
['a', 'b']
>>> fd
FrozenDict('a'=1, 'b'=2)
"""
def __init__(self, **kwargs):
self.__kwargs = kwargs
self.__next__ = self.next
self.__counter = 0
self.__init__ = None
def __repr__(self):
kwargs = ["%r=%r" % (k, v) for k, v in sorted(self.__kwargs.items())]
return "%s(%s)" % (self.__class__.__name__, ", ".join(kwargs))
def __getitem__(self, key):
return self.__kwargs[key]
def __iter__(self):
return iter(self.__kwargs)
def next(self):
try:
value = self.__kwargs.items()[self.__counter][0]
except IndexError:
raise StopIteration
self.__counter += 1
return value
def __len__(self):
return len(self.__kwargs)
class ChillyDict(dict):
"""A dictionary that does not support item assignment after initialization
>>> cd = ChillyDict(a=1, b=2)
>>> cd["a"]
1
>>> cd["a"] = 777 # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
NotImplementedError: 'ChillyDict' object does not support item assignment
>>> sorted(cd.items())
[('a', 1), ('b', 2)]
>>> sorted(cd.keys())
['a', 'b']
>>> cd
ChillyDict('a'=1, 'b'=2)
"""
def __init__(self, **kwargs):
self.__kwargs = kwargs
super(ChillyDict, self).__init__(**self.__kwargs)
self.__init__ = None
def __repr__(self):
kwargs = ["%r=%r" % (k, v) for k, v in sorted(self.__kwargs.items())]
return "%s(%s)" % (self.__class__.__name__, ", ".join(kwargs))
def __not_implemented(self, *args, **kwargs):
msg = "'%s' object does not support item assignment"
raise NotImplementedError, msg % self.__class__.__name__
__setitem__ = __delitem__ = update = pop = popitem = clear = __not_implemented
if __name__ == "__main__":
import doctest
doctest.testmod()
More information about the Tutor
mailing list