This question already has an answer here:
I have a wrapper class similar to this (strongly simplified) example:
class wrap(object):
def __init__(self):
self._data = range(10)
def __getitem__(self, key):
return self._data.__getitem__(key)
I can use it like this:
w = wrap()
print w[2] # yields "2"
I thought I could optimize and get rid of one function call by changing to this:
class wrap(object):
def __init__(self):
self._data = range(10)
self.__getitem__ = self._data.__getitem__
However, I receive a
TypeError: 'wrap' object does not support indexing
for the print w[2]
line with the latter version.
The direct call to the method, i.e., print w.__getitem__(2)
, works in both cases...
Why does the assignment version not allow indexing?
Special methods (essentially anything with two underscores on each end) have to be defined on the class. The internal lookup procedure for special methods completely skips the instance dict. Among other things, this is so if you do
the
__repr__
method you defined is only used for instances ofFoo
, and not forrepr(Foo)
.You can actually solve this by creating a new class for every type. If you want this to work transparently,
__new__
is the place for it.Initial "solution":
Be careful however! This will do what you want - use the wrapped class'
__getitem__
. However, this doesn't always make sense! For example,list.__getitem__
is actually built into CPython's CAPI and not applicable to other types.