Question

This is a very contrived example as it's not easy to explain the context in which I have ended up implementing this solution. However, if anyone can answer why this particular peculiarity happens, I'd be grateful.

The example:

class A(dict):  
    def __init__(self):
        self['a'] = 'success'

    def __getitem__(self, name):
        print 'getitem'
        return dict.__getitem__(name)

class B(object):
    def __init__(self):
        self._a = A()
        setattr(self, '__getitem__', self._a.__getitem__) 

b = B()
c = b['a']

This outputs:

c = b['a']
TypeError: 'B' object is unsubscriptable

Even though it's a bizarre way of doing this (clearly subclassing would be more logical), why doesn't it find the method I have explicitly set?

If I do this:

dir(b)

I get this:

['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', '_a']

The same issue occurs with other methods such as __iter__. What is it about explicitly defining this method that works?

Was it helpful?

Solution

When you use brackets [] python looks in the class. You must set the method in the class.

Here's your code adapted:

class A(dict):  
    def __init__(self):
        self['a'] = 'success'

    def __getitem__(self, name):
        print 'getitem!'
        return dict.__getitem__(self, name)

class B(object):
    def __init__(self):
        self._a = A()
        B.__getitem__ = self._a.__getitem__

b = B()
c = b['a']

OTHER TIPS

This is because you can't override special class methods on the fly.

I wasn't able to find a reference about this but is basically because they are class methods and are not allowed to be instance methods.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top