为什么在类上定义__getitem__使它在python中可迭代?

gri*_*eve 58 python iterator overloading

为什么在类上定义__getitem__使其可迭代?

例如,如果我写:

class b:
  def __getitem__(self, k):
    return k

cb = b()

for k in cb:
  print k
Run Code Online (Sandbox Code Playgroud)

我得到输出:

0
1
2
3
4
5
6
7
8
...
Run Code Online (Sandbox Code Playgroud)

我真的希望看到"for c in cb:"中返回的错误

Ale*_*lli 62

迭代的支持__getitem__可被视为"遗留特征",当PEP234引入可迭代性作为主要概念时,它允许更平滑的过渡.它仅适用于类,而__iter____getitem__接受整数0,1,&C,并提出IndexError一旦指数过高(如果有的话),典型的"序列"类编码之前__iter__出现(虽然没有从编码新类也以此方式阻止你).

就个人而言,我宁愿不在新代码中依赖它,虽然它没有被弃用,也不会消失(在Python 3中也能正常工作),所以这只是风格和品味的问题("明确比隐含更好"所以我宁愿明确地支持迭代,而不是依赖于__getitem__隐式支持它 - 但是,不是一个大问题.

  • 只是注意到 pythons int 没有限制。它是一个任意大小的整数。 (2认同)

Edw*_*ale 48

如果你看看定义迭代器的PEP234,它会说:

1. An object can be iterated over with "for" if it implements
   __iter__() or __getitem__().

2. An object can function as an iterator if it implements next().
Run Code Online (Sandbox Code Playgroud)

  • 这个回复的用处类似于如果一个孩子问为什么天空是蓝色的并且你回答"因为上帝做到了".在这里,有一些我的讽刺. (9认同)

Bri*_*ian 26

__getitem__早于迭代器协议,并且在过去是使事物可迭代的唯一方法.因此,它仍然作为迭代方法得到支持.本质上,迭代协议是:

  1. 检查__iter__方法.如果存在,请使用新的迭代协议.

  2. 否则,尝试__getitem__连续调用更大的整数值,直到它引发IndexError.

(2)曾经是这样做的唯一方法,但是它的缺点在于它假定比支持迭代所需的更多.为了支持迭代,你必须支持随机访问,这对于像前进很容易的文件或网络流这样的东西来说要贵得多,但倒退需要存储所有内容. __iter__允许迭代没有随机访问,但由于随机访问通常允许迭代,并且因为破坏向后兼容性将是坏的,__getitem__仍然支持.


Fog*_*ird 6

特殊方法,例如__getitem__向对象添加特殊行为,包括迭代.

http://docs.python.org/reference/datamodel.html#object.的GetItem

"for循环期望为非法索引引发IndexError,以允许正确检测序列的结尾."

提高IndexError以指示序列的结束.

您的代码基本上等同于:

i = 0
while True:
    try:
        yield object[i]
        i += 1
    except IndexError:
        break
Run Code Online (Sandbox Code Playgroud)

对象是你在for循环中迭代的对象.


Ant*_*sma 5

出于历史原因,这是如此.在Python 2.2之前,__ getitem__是创建可以使用for循环迭代的类的唯一方法.在2.2中添加了__iter__协议但是为了保持向后兼容性__getitem__仍然适用于for循环.