为什么在使用__getitem__进行迭代时调用__len__而不使用结果?

三亚什

考虑以下示例:

import random


class Class1:
    def __getitem__(self, item):
        print('getitem', item)
        result = random.randint(0, 10)
        if not result:
            raise IndexError
        return result


class Class2(Class1):
    def __len__(self):
        print('len', 3)
        return 3


print(list(Class1()))
print(list(Class2()))

输出:

getitem 0
getitem 1
[10]
len 3
getitem 0
getitem 1
getitem 2
getitem 3
getitem 4
[8, 10, 2, 10]

因此,进行遍历时Class1()没有,__len__但是代码可以正常工作。当有__len__Class2()它被称为但是结果3完全不使用迭代获得3项后继续。我的问题是:为什么__len__叫?如果结果被忽略,则没有理由调用它。

蒂埃里·拉图耶(Thierry Lathuille)

PEP 424中有一些指示:一种公开长度提示的方法

CPython当前在几种类型上定义了length_hint方法,例如各种迭代器。然后,各种其他功能(例如list)将使用此方法来根据length_hint返回的估计值对列表进行大小调整然后,没有大小且因此不应定义len的类型可以定义length_hint,以允许估计或计算大小(例如许多迭代器)。

和:

能够根据由length_hint估计的预期大小来预分配列表可能是一项重大的优化。观察到CPython比PyPy运行某些代码快,完全是因为存在这种优化。

因此似乎为了进行预分配而进行list调用__len__之后,您的列表可以根据需要增加。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么mypy如果具有__len__和__getitem__但没有__iter__,则不将其视为可迭代的类

为什么在使用[:]时不调用子类的__getitem__和__setitem__?

为什么不使用C ++调用Destructor?

为什么在使用HashMap的or_insert时调用闭包?

为什么列表询问__len__?

为什么GCC在不使用libc的sqrt()的情况下调用它的结果?

为什么视图控制器的deinit不使用RXSwift进行调用?

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

为什么Python的'len'函数比__len__方法要快?

为什么多个列表索引可以与__getitem__一起使用,而不能与__setitem__一起使用?

为什么 compareTo 不使用日期返回结果

为什么 onchange 函数不使用 Jquery 调用 DropDownList?

为什么不使用std :: getline就能调用getline?

Automapper - 为什么不使用 SourceMember 属性进行映射

为什么不使用std :: {self,...};进行编译?

mysql为什么不使用键进行简单选择?

为什么不使用表格在HTML中进行布局?

为什么toctree不使用RTD主题进行更新?

RxSwift,为什么不使用 .never() 进行测试

为什么postgres进行表扫描而不使用我的索引?

为什么我的脚本不使用keyup进行换行?

为什么不使用MathML进行overflow =“ linebreak”操作?

为什么volatile不使用std :: min进行编译

为什么不使用Flexbox对HTML表格行进行排序?

为什么不使用AWS API进行AWS SNS确认?

为什么 MongoDB 不使用复合索引进行查询?

在 Python 中不使用 for 循环进行迭代

在python中使用__getitem__遍历字典

在python中使用__getitem__遍历字典