我知道,一般来说,迭代列表比迭代集合或字典键(在某种程度上)更快。确认:
import timeit
list_setup = 'my_list = list(range(100))'
list_stmt = 'for n in my_list: n**2'
print(f'list : {timeit.timeit(setup=list_setup, stmt=list_stmt, number=100000)}')
set_setup = 'my_set = set(range(100))'
set_stmt = 'for n in my_set: n**2'
print(f'set : {timeit.timeit(setup=set_setup, stmt=set_stmt, number=100000)}')
dict_setup = 'my_dict = {n: None for n in range(100)}'
dict_stmt = 'for n in my_dict.keys(): n**2'
print(f'dict : {timeit.timeit(setup=dict_setup, stmt=dict_stmt, number=100000)}')
产生:
list : 5.110044667
set : 5.137189292
dict : 5.179844875000001
但是如果字典的值是对象而不是None
,则迭代字典键会明显更快:
dict_obj_setup = '''
class MyClass(object):
pass
my_dict_obj = {n: MyClass() for n in range(100)}
'''
dict_obj_stmt = 'for n in my_dict_obj.keys(): n**2'
print(f'dict_obj: {timeit.timeit(setup=dict_obj_setup, stmt=dict_obj_stmt, number=100000)}')
dict_obj: 1.7423309159999985
为什么会发生这种情况?如果我有一组整数需要迭代很多很多次,我是否应该创建一个字典,其键是我的整数,其值是任何随机对象?!
顺便说一句,如果我在所有循环中使用n*n
而不是
n**2
,差异就会消失:
list : 0.32518725
set : 0.344315166
dict : 0.3399045409999999
dict_obj: 0.3662140410000001
n**2
比
n*n
更复杂的操作。 因为在这种情况下功率是可变的。所以 n**x 不完全是这样,但工作方式如下:
x = 5
total = n
for _ in range(x):
total += total * n
但是n*n*n*n*n
不那么复杂。所以这两个过程的区别就是这样的。一个是动态工作的。其中之一是预先确定的。
第二,如果你用大数据来做这件事,你会发现结果会收敛,并且没有显着差异。
my_dict = {n: None for n in range(10000)}
my_list = list(range(10000))
%%timeit
for n in my_list: n**2
>>1.95 ms ± 6.69 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit
for n in my_dict.keys(): n**2
>>1.96 ms ± 5.18 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)