K
kj
Following a suggestion from MRAB, I attempted to implement a
frozendict class. My implementation took a lot more work than
something this simple should take, and it still sucks. So I'm
hoping someone can show me a better way. Specifically, I'm hoping
that there is a "recipe" for building off standard classes that
cover all the bases with a minimum of tedious repetitive work.
Here's my little monster:
ass frozendict():
_DESTRUCTIVE = set(('__delitem__ __setitem__ clear pop popitem setdefault '
'update').split())
_NON_DESTRUCTIVE = set(('__contains__ __format__ __getitem__ __hash__ '
'__init__ __iter__ __len__ __repr__ __sizeof__ '
'__str__ copy fromkeys get has_key items iteritems '
'iterkeys itervalues keys values'.split()))
_COMPARISONS = set(('__cmp__ __eq__ __ge__ __gt__ __le__ __lt__ '
'__ne__').split())
def __init__(self, iterable=(), **kwargs):
self._dict = dict(iterable, **kwargs)
def __hash__(self):
return hash(tuple(self.items()))
def __getattr__(self, attrib):
class_ = self.__class__
dict_ = self._dict
if attrib in class_._COMPARISONS:
return lambda x: dict_.__getattribute__(attrib)(x._dict)
elif attrib in class_._NON_DESTRUCTIVE:
return dict_.__getattribute__(attrib)
else:
if attrib in class_._DESTRUCTIVE:
raise TypeError("'%s' object is not mutable" % class_.__name__)
else:
raise AttributeError("'%s' object has no attribute '%s'" %
(class_.__name__, attrib))
I didn't implement this as a subclass of dict to avoid having to
write a dumb little "blocking" method for every destructive dict
method. (I couldn't figure out how to write a loop to define these
overriding methods programmatically, because their signatures are
all over the place.)
I didn't implement it as a subclass of object with an internal dict
delegate, because I couldn't figure a reasonable way to pass certain
object methods to the delegate (since in this case frozendict.__getattr__
wouldn't be called).
The handling of comparison methods is particularly horrific and
inefficient.
If "Beautiful is better than ugly", I sure how there's another way
that is a lot more beautiful than this one.
TIA!
~kj
frozendict class. My implementation took a lot more work than
something this simple should take, and it still sucks. So I'm
hoping someone can show me a better way. Specifically, I'm hoping
that there is a "recipe" for building off standard classes that
cover all the bases with a minimum of tedious repetitive work.
Here's my little monster:
ass frozendict():
_DESTRUCTIVE = set(('__delitem__ __setitem__ clear pop popitem setdefault '
'update').split())
_NON_DESTRUCTIVE = set(('__contains__ __format__ __getitem__ __hash__ '
'__init__ __iter__ __len__ __repr__ __sizeof__ '
'__str__ copy fromkeys get has_key items iteritems '
'iterkeys itervalues keys values'.split()))
_COMPARISONS = set(('__cmp__ __eq__ __ge__ __gt__ __le__ __lt__ '
'__ne__').split())
def __init__(self, iterable=(), **kwargs):
self._dict = dict(iterable, **kwargs)
def __hash__(self):
return hash(tuple(self.items()))
def __getattr__(self, attrib):
class_ = self.__class__
dict_ = self._dict
if attrib in class_._COMPARISONS:
return lambda x: dict_.__getattribute__(attrib)(x._dict)
elif attrib in class_._NON_DESTRUCTIVE:
return dict_.__getattribute__(attrib)
else:
if attrib in class_._DESTRUCTIVE:
raise TypeError("'%s' object is not mutable" % class_.__name__)
else:
raise AttributeError("'%s' object has no attribute '%s'" %
(class_.__name__, attrib))
I didn't implement this as a subclass of dict to avoid having to
write a dumb little "blocking" method for every destructive dict
method. (I couldn't figure out how to write a loop to define these
overriding methods programmatically, because their signatures are
all over the place.)
I didn't implement it as a subclass of object with an internal dict
delegate, because I couldn't figure a reasonable way to pass certain
object methods to the delegate (since in this case frozendict.__getattr__
wouldn't be called).
The handling of comparison methods is particularly horrific and
inefficient.
If "Beautiful is better than ugly", I sure how there's another way
that is a lot more beautiful than this one.
TIA!
~kj