2017-01-04 32 views
0

我的问题:为什么不调用__getattr__进行索引操作?

似乎__getattr__不叫索引操作,即我不能使用__getattr__上一类A提供A[...]。是否有一个原因?还是一种避开它的方式,以便__getattr__可以提供该功能,而无需在A上明确定义__getitem____setitem__等?

小例子:

比方说,我定义了两个几乎相同的类,ExplicitImplicit。每个都在创建时创建一个小列表self._arr,并且每个都定义了一个__getattr__,它将所有属性请求传递给self._arr。唯一的区别是Explicit也定义了__getitem__(通过将它传递给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 
+6

因为这就是Python的设计原理。 '__getattr__'用于属性访问,'__getitem__'用于索引访问。每个人都有特定的角色。我不确定这个问题是什么 – 3Doubloons

+1

[This answer](http://stackoverflow.com/a/10376655/2096752)解释它。 – shx2

+2

至于为什么他们是单独的操作,请考虑这一点:'d = {'keys':0}'在这种情况下,'d.keys'和'd ['keys']'是非常不同的东西 – 3Doubloons

回答

1

的Python绕过__getattr____getattribute__和实例字典实施语言机制。 (大多数情况下,特殊方法是在名称的每一侧都带有两个下划线的方法。)如果您期待i[0]调用i.__getitem__(0),这又会调用i.__getattr__('__getitem__')(0),这就是为什么没有发生。

+1

对于任何人来说,上面的@ shx2的评论链接到[与此有关的参考问题](http://stackoverflow.com/a/10376655/2096752)。 –

相关问题