[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