为什么不为索引操作调用__getattr__? [英] Why is __getattr__ not called for indexing operations?

查看:59
本文介绍了为什么不为索引操作调用__getattr__?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题:

似乎没有为索引操作调用__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?

最小示例:

比方说,我定义了两个几乎相同的类,即ExplicitImplicit.每个对象在启动时都会创建一个小列表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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆