On Wed, 30 Dec 2015 08:35:57 -0700, Ian Kelly wrote: > On Dec 30, 2015 7:46 AM, "Charles T. Smith" > <cts.private.ya...@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 -- https://mail.python.org/mailman/listinfo/python-list