运行此:
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应用于iniparse之后,我发现了一个令人讨厌的副作用。将__getattr__
设置在我的Undefined
类上,该类返回一个新的Undefined
对象。不幸的是,这意味着list(iniconfig.invalid_section)
(isinstance(iniconfig, iniparse.INIConfig)
}正在执行此操作(在print
和__getattr__
中添加简单__getitem__
):
Getting attr __length_hint__
Getting item 0
Getting item 1
Getting item 2
Getting item 3
Getting item 4
等等无限期。
答案 0 :(得分:7)
如果要覆盖迭代,则只需在类中定义__iter__
方法
答案 1 :(得分:3)
只需举起IndexError
而不是KeyError
。 KeyError
适用于类似地图的类(例如dict
),而IndexError
适用于序列。
如果在类上定义__getitem__()
方法,Python将自动从中生成迭代器。迭代器终止于IndexError
- 请参阅PEP234。
答案 2 :(得分:3)
正如@Sven所说,这是错误的错误。但这不是重点,重点在于它已被破坏,因为它不是你应该做的事情:阻止__getattr__
提升AttributeError
意味着你已经覆盖了Python的默认方法测试对象是否具有属性并将其替换为新属性(ini_defined(foo.bar)
)。
但是Python已经有hasattr
了!为什么不使用它?
>>> class Foo:
... bar = None
...
>>> hasattr(Foo, "bar")
True
>>> hasattr(Foo, "baz")
False
答案 3 :(得分:1)
通过实现__iter__()
方法覆盖您的类的迭代方式。迭代器通过引发StopIteration
异常完成时发出信号,这是正常迭代器协议的一部分,不会进一步传播。以下是将其应用于示例类的一种方法:
class DontList(object):
def __getitem__(self, key):
print 'Getting item %s' % key
if key == 10: raise KeyError("You get the idea.")
return None
def __iter__(self):
class iterator(object):
def __init__(self, obj):
self.obj = obj
self.index = -1
def __iter__(self):
return self
def next(self):
if self.index < 9:
self.index += 1
return self.obj[self.index]
else:
raise StopIteration
return iterator(self)
list(DontList())
print 'done'
# Getting item 0
# Getting item 1
# ...
# Getting item 8
# Getting item 9
# done
答案 4 :(得分:0)
我认为使用return iter([])
是正确的方法,但让我们开始考虑list()
的工作方式:
从__iter__
获取元素;如果收到StopIrteration
错误则停止..然后获取该元素..
所以你只需yield
__iter__
(x for x in xrange(0, 0))
中的空生成器,例如iter([]))
,或只是{{1}}