为什么在使用 __getitem__ 迭代时调用了 __len__ 并且没有使用结果?

Why __len__ is called and the result is not used when iterating with __getitem__?(为什么在使用 __getitem__ 迭代时调用了 __len__ 并且没有使用结果?)
本文介绍了为什么在使用 __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__ 并且没有使用结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Leetcode 234: Palindrome LinkedList(Leetcode 234:回文链接列表)
How do I read an Excel file directly from Dropbox#39;s API using pandas.read_excel()?(如何使用PANDAS.READ_EXCEL()直接从Dropbox的API读取Excel文件?)
subprocess.Popen tries to write to nonexistent pipe(子进程。打开尝试写入不存在的管道)
I want to realize Popen-code from Windows to Linux:(我想实现从Windows到Linux的POpen-code:)
Reading stdout from a subprocess in real time(实时读取子进程中的标准输出)
How to call type safely on a random file in Python?(如何在Python中安全地调用随机文件上的类型?)