如何重写Python列表(迭代器)行为?

2024-05-19 10:22:39 发布

您现在位置: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,但没有帮助。)

我的真实用例:(如果有用的话,请仔细阅读;可以忽略这一点)

在将a certain patch应用到InParse之后,我发现我的补丁有一个令人讨厌的副作用。在我的类上设置__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

等等。


Tags: thekeyselfyougetreturndefitem
3条回答

正如@Sven所说,这是错误的错误。但这并不是重点,关键是它被破坏了,因为它不是您应该做的事情:阻止__getattr__提升AttributeError意味着您已经重写了Python测试对象是否有属性的默认方法,并将其替换为新的属性(ini_defined(foo.bar))。

但是Python已经有了^{}!为什么不用那个?

>>> class Foo:
...     bar = None
...
>>> hasattr(Foo, "bar")
True
>>> hasattr(Foo, "baz")
False

只需提高IndexError,而不是KeyErrorKeyError用于映射类(例如dict),而IndexError用于序列。

如果在类上定义^{}方法,Python将自动从中生成迭代器。迭代器终止于IndexError——参见PEP234

如果要重写迭代,那么只需在类中定义__iter__方法

相关问题 更多 >

    热门问题