我在Python中没有[]读过关于列表理解的内容,所以现在我知道了
''.join([str(x) for x in mylist])
Run Code Online (Sandbox Code Playgroud)
比...更快
''.join(str(x) for x in mylist)
Run Code Online (Sandbox Code Playgroud)
因为"列表推导得到高度优化"
所以我认为优化依赖于for表达式的解析,查看mylist,计算其长度,并使用它来预先分配精确的数组大小,这节省了大量的重新分配.
使用时''.join(str(x) for x in mylist),join盲目地接收发电机,并且必须在不事先知道尺寸的情况下建立其列表.
但现在考虑一下:
mylist = [1,2,5,6,3,4,5]
''.join([str(x) for x in mylist if x < 4])
Run Code Online (Sandbox Code Playgroud)
python如何决定列表理解的大小?它是根据大小计算的mylist,并且在迭代完成时缩小(如果列表很大并且条件过滤掉99%的元素,这可能非常糟糕),或者它是否会恢复为"不知道提前大小"案例?
编辑:我做了一些小基准测试,似乎确认有一个优化:
没有条件:
import timeit
print(timeit.timeit("''.join([str(x) for x in [1,5,6,3,5,23,334,23234]])"))
print(timeit.timeit("''.join(str(x) for x in [1,5,6,3,5,23,334,23234])"))
Run Code Online (Sandbox Code Playgroud)
收益率(如预期):
3.11010817019474
3.3457350077491026
Run Code Online (Sandbox Code Playgroud)
有条件:
print(timeit.timeit("''.join([str(x) for x in [1,5,6,3,5,23,334,23234] if x < 50])"))
print(timeit.timeit("''.join(str(x) for x in [1,5,6,3,5,23,334,23234] if …Run Code Online (Sandbox Code Playgroud) 我有以下两个功能:
def foo(n=50000):
return sum(i*i for i in range(n)) # just called sum() directly without
def bar(n=50000):
return sum([i*i for i in range(n)]) # passed constructed list to sum()
Run Code Online (Sandbox Code Playgroud)
我希望那foo会跑得更快,bar但我已经检查了ipython,%%timeit那foo时间稍长bar
In [2]: %%timeit
...: foo(50000)
...:
100 loops, best of 3: 4.22 ms per loop
In [3]: %%timeit
...: bar(50000)
...:
100 loops, best of 3: 3.45 ms per loop
In [4]: %%timeit
...: foo(10000000)
...:
1 loops, best of 3: …Run Code Online (Sandbox Code Playgroud) 不确定标题是否是正确的术语。
如果您必须比较 2 个字符串 (A,B) 中的字符并计算 B 中字符与 A 的匹配次数:
sum([ch in A for ch in B])
Run Code Online (Sandbox Code Playgroud)
在 %timeit 上比
sum(ch in A for ch in B)
Run Code Online (Sandbox Code Playgroud)
我知道第一个将创建一个 bool 列表,然后对 1 的值求和。第二个是生成器。我不清楚它在内部做什么以及为什么它变慢了?
谢谢。
使用 %timeit 结果进行编辑:
10 个字符
生成器表达式
列表
10000 个循环,最好的 3 个:每个循环 112 µs
10000 个循环,最好的 3 个:每个循环 94.6 µs
1000 个字符
生成器表达式
列表
100 个循环,最好的 3 个:每个循环 8.5 毫秒
100 个循环,最好的 3 个:每个循环 6.9 毫秒
10,000 个字符
生成器表达式
列表
10 个循环,最好的 3 个:每个循环 87.5 毫秒
10 个循环,最好的 …
所以我从官方文档中得到了这些例子. https://docs.python.org/2/library/timeit.html
究竟是什么让第一个例子(生成器表达式)比第二个(列表理解)慢?
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.8187260627746582
>>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000)
0.7288308143615723
Run Code Online (Sandbox Code Playgroud) 我有一个包含嵌套列表的列表,我需要知道在这些嵌套列表中搜索的最有效方法.
例如,如果我有
[['a','b','c'],
['d','e','f']]
Run Code Online (Sandbox Code Playgroud)
我必须搜索上面的整个列表,找到'd'的最有效方法是什么?
我想知道它:
> %timeit sum([int(digit) for digit in str(n)])
100000 loops, best of 3: 1.52 us per loop
> %timeit sum(int(digit) for digit in str(n))
100000 loops, best of 3: 2.04 us per loop
Run Code Online (Sandbox Code Playgroud) 目前我正在学习生成器和列表理解,并且弄乱了剖析器以查看性能增益,并且在这两个中使用两者中的大量素数的总和数量的混乱.
我可以在生成器中看到:1 genexpr作为累积时间方式比列表对应方式短,但第二行是令我感到困惑的.正在做一个我认为是数字检查的电话是素数,但是不应该是另一个:列表理解中的1个模块?
我在个人资料中遗漏了什么吗?
In [8]: cProfile.run('sum((number for number in xrange(9999999) if number % 2 == 0))')
5000004 function calls in 1.111 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
5000001 0.760 0.000 0.760 0.000 <string>:1(<genexpr>)
1 0.000 0.000 1.111 1.111 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.351 0.351 1.111 1.111 {sum}
In [9]: cProfile.run('sum([number for number in xrange(9999999) if number % 2 == 0])')
3 function calls in 1.123 seconds …Run Code Online (Sandbox Code Playgroud) Python 3.6.8 (default, Oct 7 2019, 12:59:55)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.9.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: def yield_from_generator():
...: yield from (i for i in range(10000))
...:
In [2]: def yield_from_list():
...: yield from [i for i in range(10000)]
...:
In [3]: import timeit
In [4]: timeit.timeit(lambda: list(yield_from_generator()), number=10000)
Out[4]: 5.3820097140014695
In [5]: timeit.timeit(lambda: list(yield_from_list()), number=10000)
Out[5]: 4.333915593000711
Run Code Online (Sandbox Code Playgroud)
我多次运行yield from生成器并yield from列出。列表版本总是提供更好的性能,而我的直觉告诉我相反的结论 - 制作列表需要在启动时分配内存。为什么我们可以注意到这种性能差异?
如果迭代完成但没有被中断,则/ 子句中的else块被执行,所以我读了.forelsebreak
是否有一种语言结构可以让我写一些只有在for循环没有开始迭代时执行的东西?如果我正在使用tuple或list,我会做这样的事情:
if seq:
for x in seq:
# something
else:
# something else
Run Code Online (Sandbox Code Playgroud)
但是当我使用生成器时,我没有得到我想要的行为:
>>> g = (x for x in range(2))
>>> for x in g:
... print x
... else:
... print "done"
...
0
1
done # I don't want "done" here
>>> g = (x for x in range(2) if x > 1)
>>> if g:
... for x in g: …Run Code Online (Sandbox Code Playgroud) 首先,我想测试生成器和列表理解之间的内存使用情况.本书给了我一个小小的代码片段,我在我的PC上运行它(python3.6,Windows),发现一些意想不到的东西.
FOllowing是我的代码,它不满足以前的意见(在sum函数中).
import tracemalloc
from time import time
def timeIt(func):
start = time()
func()
print('%s use time' % func.__name__, time() - start)
return func
tracemalloc.start()
numbers = range(1, 1000000)
@timeIt
def lStyle():
return sum([i for i in numbers if i % 3 == 0])
@timeIt
def gStyle():
return sum((i for i in numbers if i % 3 == 0))
lStyle()
gStyle()
shouldSize = [i for i in numbers if i % 3 == 0]
snapshotL = tracemalloc.take_snapshot()
top_stats …Run Code Online (Sandbox Code Playgroud) python ×10
generator ×4
python-2.7 ×2
python-3.x ×2
coroutine ×1
list ×1
loops ×1
performance ×1
profiling ×1
string ×1
sum ×1
yield ×1