考虑以下示例:
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__但是代码可以正常工作。当有__len__在Class2()它被称为但是结果3完全不使用迭代获得3项后继续。我的问题是:为什么__len__叫?如果结果被忽略,则没有理由调用它。
Class1()
__len__
Class2()
3
PEP 424中有一些指示:一种公开长度提示的方法:
CPython当前在几种类型上定义了 length_hint 方法,例如各种迭代器。然后,各种其他功能(例如list)将使用此方法来根据 length_hint 返回的估计值对列表进行 大小调整 。然后,没有大小且因此不应定义 len的类型 可以定义 length_hint ,以允许估计或计算大小(例如许多迭代器)。 和: 能够根据由 length_hint 估计的预期大小来预分配列表可能是一项重大的优化。观察到CPython比PyPy运行某些代码快,完全是因为存在这种优化。
CPython当前在几种类型上定义了 length_hint 方法,例如各种迭代器。然后,各种其他功能(例如list)将使用此方法来根据 length_hint 返回的估计值对列表进行 大小调整 。然后,没有大小且因此不应定义 len的类型 可以定义 length_hint ,以允许估计或计算大小(例如许多迭代器)。
和:
能够根据由 length_hint 估计的预期大小来预分配列表可能是一项重大的优化。观察到CPython比PyPy运行某些代码快,完全是因为存在这种优化。
因此,似乎要进行list调用__len__才能预先分配列表。之后,您的列表可以根据需要增加。
list