gpt4 book ai didi

自定义类型的 python 列表构造函数-长度调用两次

转载 作者:行者123 更新时间:2023-12-04 15:11:47 26 4
gpt4 key购买 nike

考虑以下 python 代码:

class View:
pass


v = View()
print(list(v))

运行时出现如下错误:

Traceback (most recent call last):
File "testing.py", line 35, in <module>
print(list(v))
TypeError: 'View' object is not iterable

有道理。让我们将 __iter__ 添加到 View

class View:
def __iter__(self):
for i in range(5):
yield i

现在可以正常工作,并正确生成 [0, 1, 2, 3, 4]

但是,考虑一下如果 View 定义了 __len__ 方法会发生什么:

class View:
def __len__(self):
print("len called")
return 2

def __iter__(self):
for i in range(5):
yield i

v = View()
print(list(v))

运行时,会产生:

len called
len called
[0, 1, 2, 3, 4]

不仅 __len__ 被调用了两次,它似乎也没有被“尊重”(我返回 2 作为长度,但我的 __iter__ 产生了 5 个值,并且列表正确地由 5 个值组成)

这是怎么回事? (请注意,这不是一个无聊的好奇心。在我的应用程序中,我有一个昂贵的 __len__ 方法并且调用它两次会减慢我的初始化时间)

最佳答案

根据 Why does list ask about __len__?调用 __len__ 方法来估计需要为列表分配多少空间。请注意,这只是一个近似值,无论您是使用 __iter__ 还是 __getitem__ 进行迭代,长度都没有约束力:

>>> class GetItemIter:
... def __len__(self):
... return 2
... def __getitem__(self, index):
... return [0, 1, 2][index]
...
>>> list(GetItemIter())
[0, 1, 2]
>>> class IterIter:
... def __len__(self):
... return 2
... def __iter__(self):
... return iter([0, 1, 2])
...
>>> list(IterIter())
[0, 1, 2]

从 Python 3.8 开始,列表构造函数是 checking the length twice .这是在错误跟踪器中,但可以被视为实现细节:

The number of times we can __len__ on the constructor is animplementation detail. The reason is called now twice is because thereis an extra check for the preallocation logic...

关于自定义类型的 python 列表构造函数-长度调用两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65097930/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com