> From: sjeik_ap...@hotmail.com > To: tutor@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() _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor