trap attributeError from inside a dict ?
Peter Otten
__peter__ at web.de
Wed Mar 10 05:04:51 EST 2004
GrelEns wrote:
> hello,
>
> i would like if this behaviour can be obtained from python : trap an
> attributeError from inside a subclassing dict class... (here is a silly
> examples to explain my question)
>
> class Test(dict):
> """subclassing a dict and each key will permit access to a tuple of fized
> size"""
> def __init__(self):
> pass
> def load(self, adict):
> """actually it will be done from a text file with fixed size fields,
> each
> tuple will have the same size"""
> for k in adict:
> self[k] = tuple(adict[k])
>
> t = Test()
> t.load({1: ('a', 'aa'), 2: ('(b', 'bb')})
>
> here is what i would have :
>>>> t[1].get('first')
> 'a'
>
> without having to define tuple as an object or subclassing tuple, of
> course now i had :
>>>> t[1].get('first')
>
> Traceback (most recent call last):
> File "<pyshell#15>", line 1, in -toplevel-
> t['A'].get('first')
> AttributeError: 'tuple' object has no attribute 'get'
>
> is it possible ?
>
> btw my question is something like is there a way from inside Test code to
> say to python that when it first get t[1] it should not go further, trap
> the things one ask to do on t[key] and then calling a function such as
>
> (inside Test)
> def __get(self, key, readable):
> mapping = {'first' : 1, 'second' : 2}
> return self[key][mapping[readable]]
>
> (maybe it is a silly design...but i need this because i do want some kind
> of readable object access without having to create all these objects)
Here's one way to do it:
>>> class Dict(dict):
... translate = {"first": 0, "second": 1}
... def __getitem__(self, key):
... value = dict.__getitem__(self, key[0])
... return value[self.translate[key[1]]]
...
>>> d = Dict([(1,("a", "aa")), (2, ("b", "bb"))])
>>> d[1, "first"]
'a'
>>> d[2, "second"]
'bb'
Here's another:
>>> class Dict(dict):
... def __getitem__(self, key):
... return Wrap(dict.__getitem__(self, key))
...
>>> class Wrap(object):
... def __init__(self, data): self.data = data
... first = property(lambda self: self.data[0])
... second = property(lambda self: self.data[1])
...
>>> d = Dict([(1,("a", "aa")), (2, ("b", "bb"))])
>>> d[1].first
'a'
>>> d[2].second
'bb'
>>>
Note that you might end with *more* objects as every call to __getitem__()
creates a new Wrap instance. A cache could help, but if you did it properly
with a custom class for the values the problem wouldn't arise.
Personally, I would put custom objects into a normal dictionary instead of
playing one of these tricks.
Peter
More information about the Python-list
mailing list