为什么在使用 __getitem__ 迭代时调用了 __len__ 并且没有使用结果? [英] Why __len__ is called and the result is not used when iterating with __getitem__?

查看:15
本文介绍了为什么在使用 __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__ 但代码可以正常工作.当 Class2() 中有 __len__ 时,它被调用但结果 3 根本没有使用,得到 3 个项目后继续迭代.我的问题是:为什么调用 __len__ ?如果结果被忽略,就没有理由调用它.

So, when iterating through Class1() there is no __len__ but the code works correctly. When there is __len__ in Class2() it is called but the result 3 is not used at all, the iteration continues after getting 3 items. My question is: why __len__ is called? There is no reason to call it if the result is ignored.

推荐答案

PEP 424: 一种暴露长度提示的方法:

CPython 目前在几种类型上定义了 length_hint 方法,比如各种迭代器.这种方法然后被其他各种使用函数(例如列表)根据估计来预先确定列表的大小由 length_hint 返回.没有大小的类型,因此不应该定义 len,然后可以定义 length_hint,以允许估计或计算大小(例如许多迭代器).

CPython currently defines a length_hint method on several types, such as various iterators. This method is then used by various other functions (such as list) to presize lists based on the estimate returned by length_hint. Types which are not sized, and thus should not define len, can then define length_hint, to allow estimating or computing a size (such as many iterators).

还有:

能够根据预期大小预先分配列表,如由 length_hint 估计,可能是一项重要的优化.已经观察到 CPython 运行某些代码的速度比 PyPy 快,纯粹是因为存在这种优化.

Being able to pre-allocate lists based on the expected size, as estimated by length_hint, can be a significant optimization. CPython has been observed to run some code faster than PyPy, purely because of this optimization being present.

看来 list 调用 __len__ 是为了预先分配列表.之后,您的列表可以随心所欲地增长.

So it seems that list calls __len__ in order to pre-allocate the list. Your list can grow as large as it wants after that.

这篇关于为什么在使用 __getitem__ 迭代时调用了 __len__ 并且没有使用结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆