为什么在使用__getitem__进行迭代时会调用__len__而不使用结果? [英] Why __len__ is called and the result is not used when iterating with __getitem__?

查看:67
本文介绍了为什么在使用__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.

推荐答案

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天全站免登陆