如何重写Python列表(迭代器)的行为?
运行这个:
class DontList(object):
def __getitem__(self, key):
print 'Getting item %s' % key
if key == 10: raise KeyError("You get the idea.")
return None
def __getattr__(self, name):
print 'Getting attr %s' % name
return None
list(DontList())
会产生这个:
Getting attr __length_hint__
Getting item 0
Getting item 1
Getting item 2
Getting item 3
Getting item 4
Getting item 5
Getting item 6
Getting item 7
Getting item 8
Getting item 9
Getting item 10
Traceback (most recent call last):
File "list.py", line 11, in <module>
list(DontList())
File "list.py", line 4, in __getitem__
if key == 10: raise KeyError("You get the idea.")
KeyError: 'You get the idea.'
我该如何更改它,以便我能得到 []
,同时仍然可以访问那些键 [1]
等等?
(我试过加上 def __length_hint__(self): return 0
,但没有效果。)
我的真实使用案例:(如果有用可以看看;如果觉得没必要可以忽略后面的内容)
在对 iniparse 应用了一些补丁后,我发现了一个麻烦的副作用。我的 Undefined
类上设置了 __getattr__
,它会返回一个新的 Undefined
对象。不幸的是,这意味着 list(iniconfig.invalid_section)
(其中 isinstance(iniconfig, iniparse.INIConfig)
)会这样做(在 __getattr__
和 __getitem__
中加上简单的 print
):
Getting attr __length_hint__
Getting item 0
Getting item 1
Getting item 2
Getting item 3
Getting item 4
等等,没完没了。
5 个回答
3
你可以抛出 IndexError
错误,而不是 KeyError
。KeyError
是用来处理像字典这样的映射类(比如 dict
),而 IndexError
是用来处理序列的。
如果你在你的类中定义了 __getitem__()
方法,Python 会自动为它生成一个迭代器。而这个迭代器会在遇到 IndexError
时停止运行——具体可以参考 PEP234。
7
如果你想要自定义遍历的方式,只需要在你的类里面定义一个 __iter__
方法就可以了。