【问题标题】:Why is __getattr__ not called for indexing operations?为什么不调用 __getattr__ 进行索引操作?
【发布时间】:2017-01-04 19:15:26
【问题描述】:

我的问题:

似乎没有为索引操作调用__getattr__,即我不能在类A 上使用__getattr__ 来提供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

【问题讨论】:

  • 因为这就是 Python 的设计方式。 __getattr__ 用于属性访问,__getitem__ 用于索引访问。每个人都有特定的角色。我不确定问题是什么
  • This answer 解释它。
  • 至于为什么它们是独立的操作,考虑一下:d = {'keys': 0} 在这种情况下,d.keysd['keys'] 是非常不同的东西
  • python 怎么会猜测访问Implicit 的索引会访问其成员之一的索引?这根本没有意义。
  • @shx2 谢谢,这正是我的困惑!

标签: python getattr


【解决方案1】:

在查找实现语言机制的“特殊”方法时,Python 会绕过 __getattr____getattribute__ 和实例字典。 (在大多数情况下,特殊方法是名称两边各有两个下划线的方法。)如果您期望 i[0] 调用 i.__getitem__(0),而后者又会调用 i.__getattr__('__getitem__')(0),这就是为什么没有发生这种情况.

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-25
  • 2017-06-19
  • 2020-10-08
  • 1970-01-01
  • 1970-01-01
  • 2014-02-06
  • 1970-01-01
相关资源
最近更新 更多