我正在阅读Python文档,并且在Section 8.4.1下,
我找到了以下__init__
定义(缩写):
class ListBasedSet(collections.abc.Set):
''' Alternate set implementation favoring space over speed
and not requiring the set elements to be hashable. '''
def __init__(self, iterable):
self.elements = lst = []
for value in iterable:
if value not in lst:
lst.append(value)
我没有得到的部分是self.elements = lst = []
行。为什么要进行双重任务?
添加一些打印语句:
def __init__(self, iterable):
self.elements = lst = []
print('elements id:', id(self.elements))
print('lst id:', id(lst))
for value in iterable:
if value not in lst:
lst.append(value)
声明一个:
ListBasedSet(range(3))
elements id: 4741984136
lst id: 4741984136
Out[36]: <__main__.ListBasedSet at 0x11ab12fd0>
正如所料,它们都指向相同的PyObject。
简洁是做这样事情的唯一理由吗?如果没有,为什么?与重入有关吗?
答案 0 :(得分:0)
我称之为过早优化的情况;你不能通过消除点来节省那么多,特别是对于大输入迭代;这是一些时间:
消除点:
%timeit ListBasedSet(range(3))
The slowest run took 4.06 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 2.05 µs per loop
%timeit ListBasedSet(range(30))
100000 loops, best of 3: 18.5 µs per loop
%timeit ListBasedSet(range(3000))
10 loops, best of 3: 119 ms per loop
然后,用点(即将lst
替换为self.elements
:
%timeit ListBasedSet(range(3))
The slowest run took 5.97 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 2.48 µs per loop
%timeit ListBasedSet(range(30))
10000 loops, best of 3: 22.8 µs per loop
%timeit ListBasedSet(range(3000))
10 loops, best of 3: 118 ms per loop
正如您所看到的,随着我们增加输入迭代的大小,时间上的差异几乎消失,附加和成员资格测试几乎涵盖任何收益。