为什么不为索引操作调用__getattr__? [英] Why is __getattr__ not called for indexing operations?
问题描述
我的问题:
似乎没有为索引操作调用__getattr__
,即我不能在类A
上使用__getattr__
来提供A[...]
.是否有一个原因?还是一种解决方法,以便__getattr__
可以提供该功能而不必在A
上显式定义__getitem__
,__setitem__
等?
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
?
最小示例:
比方说,我定义了两个几乎相同的类,即Explicit
和Implicit
.每个对象在启动时都会创建一个小列表self._arr
,每个对象都定义一个__getattr__
,该列表仅将所有属性请求传递给self._arr
.唯一的区别是Explicit
还定义了__getitem__
(只需将其传递给self._arr
).
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)
这可以按预期工作:
>>> e=Explicit()
>>> print(e.copy())
called __getattr_
[1, 2, 3, 4]
>>> print(hasattr(e,'__getitem__'))
True
>>> print(e[0])
1
但这不是:
>>> 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
推荐答案
Python在查找用于实现语言机制的特殊"方法时会绕过__getattr__
,__getattribute__
和实例dict. (在大多数情况下,特殊方法是在名称的两边都带有两个下划线的方法.)如果您期望i[0]
调用i.__getitem__(0)
,而这又会调用i.__getattr__('__getitem__')(0)
,这就是为什么没有发生这种情况的原因.
Python bypasses __getattr__
, __getattribute__
, and the instance dict when looking up "special" methods for implementing language mechanics. (For the most part, special methods are ones with two underscores on each side of the name.) If you were expecting i[0]
to invoke i.__getitem__(0)
, which would in turn invoke i.__getattr__('__getitem__')(0)
, that's why that didn't happen.
这篇关于为什么不为索引操作调用__getattr__?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!