| Store | Cart

trap attributeError from inside a dict ?

From: Peter Otten <__pe...@web.de>
Wed, 10 Mar 2004 11:04:51 +0100
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

Recent Messages in this Thread
GrelEns Mar 10, 2004 08:27 am
Peter Otten Mar 10, 2004 10:04 am
GrelEns Mar 10, 2004 11:14 am
Messages in this thread