using __getitem()__ correctly
Charles T. Smith
cts.private.yahoo at gmail.com
Wed Dec 30 11:58:36 EST 2015
On Wed, 30 Dec 2015 08:35:57 -0700, Ian Kelly wrote:
> On Dec 30, 2015 7:46 AM, "Charles T. Smith"
> <cts.private.yahoo at gmail.com> wrote:
>> As is so often the case, in composing my answer to your question, I
>> discovered a number of problems in my class (e.g. I was calling
>> __getitem__() myself!), but I'm puzzled now how to proceed. I thought
>> the way you avoid triggering __getattr__() from within that was to use
>> self.__dict__[name] but that doesn't work:
>>
>> (PDB)p self.attrs.keys()
>> ['mcc', 'abc']
>> (PDB)p self.attrs.__dict__['abc']
>> *** KeyError: KeyError('abc',)
>
> What leads you to believe that this is triggering a call to __getattr__?
> The KeyError probably just means that the key 'abc' wasn't found in the
> dict.
I meant, it doesn't work because I'm not getting at the attribute Although keys()
sees it, it's not in the __dict__ attribute of attrs. If it's not there, where is it?
> print "attrdict:av:__getattr__: autovivifying ", name
> #self.__dict__.__setitem__ (name, self.__class__())
> #self.__setitem__ (name, self.__class__()) self.__setattr__
> (name, self.__class__())
>
> No reason to explicitly call __setitem__ or __setattr__ here. I'd
> probably just do self[name] = self.__class__()
The reason I used this is to avoid trigging the __setitem__() method:
self.__setattr__(name, self.__class__())
which is invoked if I use the "self[name]" syntax. But that didn't work.
Is it just impossible to get at attributes without going through either
__getattr__() or __getitem__()?
> Based on the preceding, you probably want to return the value you just
> set in the dict, correct? So just return self[name].
The problem is that then triggers the __getitem__() method and I don't
know how to get to the attributes without triggering __getattr__().
It's the interplay of the two that's killing me.
In the example, if I have:
self.mcc = self.attrs.mcc
The crux:
Then __getattr__() triggers for the mcc. If I try to use self.attrs['mcc']
to get it, then that triggers __getitem__(). Okay, if the key is not an int,
I'll go and get it and return it... unfortunately that triggers __getattr__(),
an infinite loop.
I tried using:
attrdict.__getattr__ (self, 'mcc')
but that didn't help, of course. I also tried so, but I've got this wrong, somehow:
super (attrdict, self).__getattr__ ('mcc')
class attrdict(dict):
def __init__ (self, name = None):
if name:
self.update (name)
print "attrdict: instantiated: ", name
# AutoVivification
def __getattr__ (self, name):
print "attrdict:av:__getattr__: entered for ", name
if name not in self.keys():
print "attrdict:av:__getattr__: autovivifying ", name
self[name] = self.__class__()
return self[name]
def __getitem__ (self, key):
print "attrdict:av:__getitem__: entered for ", key
if type (key) is int: # TODO: support slices
return self.__getitem__(key)
return attrdict.__getattr__(self, key)
def __setattr__(self, name, value):
self[name] = value
More information about the Python-list
mailing list