My question:
It seems that __getattr__
is not called for indexing operations, ie I can't use __getattr__
on a class A
to provide A[...]
. Is there a reason for this? Or a way to get around it so that __getattr__
can provide that functionality without having to explicitly define __getitem__
, __setitem__
, etc on A
?
Minimal Example:
Let's say I define two nearly identical classes, Explicit
and Implicit
. Each creates a little list self._arr
on initiation, and each defines a __getattr__
that just passes all attribute requests to self._arr
. The only difference is that Explicit
also defines __getitem__
(by just passing it on to self._arr
).
# Passes all attribute requests on to a list it contains
class Explicit():
def __init__(self):
self._arr=[1,2,3,4]
def __getattr__(self,attr):
print('called __getattr_')
return getattr(self._arr,attr)
def __getitem__(self,item):
return self._arr[item]
# Same as above but __getitem__ not defined
class Implicit():
def __init__(self):
self._arr=[1,2,3,4]
def __getattr__(self,attr):
print('called __getattr_')
return getattr(self._arr,attr)
This works as expected:
>>> e=Explicit()
>>> print(e.copy())
called __getattr_
[1, 2, 3, 4]
>>> print(hasattr(e,'__getitem__'))
True
>>> print(e[0])
1
But this doesn't:
>>> i=Implicit()
>>> print(i.copy())
called __getattr_
[1, 2, 3, 4]
>>> print(hasattr(i,'__getitem__'))
called __getattr_
True
>>> print(i.__getitem__(0))
called __getattr_
1
>>> print(i[0])
TypeError: 'Implicit' object does not support indexing