using __getitem()__ correctly

Charles T. Smith cts.private.yahoo at gmail.com
Wed Dec 30 09:40:28 EST 2015


On Thu, 31 Dec 2015 00:11:24 +1100, Chris Angelico wrote:

> On Wed, Dec 30, 2015 at 11:57 PM, Charles T. Smith
> <cts.private.yahoo at gmail.com> wrote:
>> Hello,
>>
>> I thought __getitem__() was invoked when an object is postfixed with an
>> expression in brackets:
>>
>>   - abc[n]
>>
>> and __getattr__() was invoked when an object is postfixed with an dot:
>>
>>   - abc.member
> 
> That would be normal (with the caveat that __getattr__ is called only if
> the attribute isn't found; __getattribute__ is called unconditionally).
> 
>> but my __getitem__ is being invoked at this time, where there's no
>> subscript (going into a spiral recursion death):
>>
>>   self.mcc = self.attrs.mcc
>>
>> Can anybody explain to me why __getitem__()  would be invoked here?
> 
> Can you post your entire class, or at least __getattr__? Also check
> superclasses, if there are any.
> 
> ChrisA

(PDB)isinstance (self.attrs, attrdict)
True

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',)



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      #, " in ", self
        #if not name in self.__dict__.keys():
        if not name in self.keys():
            print "attrdict:av:__getattr__: autovivifying ", name
            #self.__dict__.__setitem__ (name, self.__class__()) 
            #self.__setitem__ (name, self.__class__())
            self.__setattr__ (name, self.__class__())
        #return self.__getitem__(name)
        #return self.__dict__.__getitem__(name)
        return self.__getattribute__ (name)

    def __getitem__ (self, key):
        print "attrdict:av:__getitem__: entered for ", key      #, " in ", self
        return self.__getitem__(key)


    def __getattr__deprecated (self, name):
        return self[name]

    def __setattr__(self, name, value):
        self[name] = value



More information about the Python-list mailing list