gpt4 book ai didi

python - 为什么 list 会询问 __len__?

转载 作者:IT老高 更新时间:2023-10-28 21:59:45 24 4
gpt4 key购买 nike

class Foo:
def __getitem__(self, item):
print('getitem', item)
if item == 6:
raise IndexError
return item**2
def __len__(self):
print('len')
return 3

class Bar:
def __iter__(self):
print('iter')
return iter([3, 5, 42, 69])
def __len__(self):
print('len')
return 3

演示:

>>> list(Foo())
len
getitem 0
getitem 1
getitem 2
getitem 3
getitem 4
getitem 5
getitem 6
[0, 1, 4, 9, 16, 25]
>>> list(Bar())
iter
len
[3, 5, 42, 69]

为什么list 调用__len__?它似乎没有将结果用于任何明显的事情。 for 循环不会这样做。 iterator protocol 中的任何地方都没有提到这一点,这里只讨论 __iter____next__

这个 Python 是提前为列表保留空间,还是类似的聪明方法?

(Linux 上的 CPython 3.6.0)

最佳答案

Rationale section from PEP 424介绍了 __length_hint__ 并提供了有关动机的见解:

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.

除此之外,文档 for object.__length_hint__验证这纯粹是一个优化功能:

Called to implement operator.length_hint(). Should return an estimated length for the object (which may be greater or less than the actual length). The length must be an integer >= 0. This method is purely an optimization and is never required for correctness.

所以 __length_hint__ 在这里是因为它可以带来一些不错的优化。

PyObject_LengthHintfirst tries to get a value from object.__len__ (if it is defined)然后尝试查看 object.__length_hint__ 是否可用。如果两者都不存在,则返回列表的默认值 8

listextend,正如 Eli 在他的回答中所说,从 list_init 调用,已根据此 PEP 进行了修改,以便为定义 的任何内容提供此优化__len____length_hint__

list 并不是唯一受益于此的,当然,bytes objects do :

>>> bytes(Foo())
len
getitem 0
...
b'\x00\x01\x04\t\x10\x19'

所以 do bytearray objects but, only when you extend them :

>>> bytearray().extend(Foo())
len
getitem 0
...

tuple 对象创建 an intermediary sequence to填充自己:

>>> tuple(Foo())
len
getitem 0
...
(0, 1, 4, 9, 16, 25)

如果有人在徘徊,为什么 'len' 在类 Bar 和不像 Foo 类那样发生:

这是因为如果手头的对象定义了一个 __iter__ Python will first call it to get the iterator ,从而也运行 print('iter') 。如果它回退到使用 __getitem__,则不会发生同样的情况。

关于python - 为什么 list 会询问 __len__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41474829/

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