【发布时间】:2016-04-19 10:10:19
【问题描述】:
假设我有一个列表:
cities = ['Berlin','London','Chicago']
我想单独打印该列表中的每个字母。
其中一种方法更有效还是更推荐?
这个:
for c in cities:
for l in c:
print l
或者这个:
for l in ''.join(cities):
print l
【问题讨论】:
假设我有一个列表:
cities = ['Berlin','London','Chicago']
我想单独打印该列表中的每个字母。
其中一种方法更有效还是更推荐?
这个:
for c in cities:
for l in c:
print l
或者这个:
for l in ''.join(cities):
print l
【问题讨论】:
“什么会更有效”通常取决于操作系统和其他因素。但是,您可以做一个非常简单的基准测试:
cities = ['Berlin','London','Chicago']
import time
start = time.time()
for x in range(100000):
for c in cities:
for l in c:
pass
end = time.time()
print "method 1: " + str(end-start)
start = time.time()
for x in range(100000):
for l in ''.join(cities):
pass
end = time.time()
print "method 1: " + str(end-start)
在带有 python 2.7 的 windows 8 上,我得到了:
method 1: 0.218999862671
method 1: 0.141000032425
我相信大多数系统都会有类似的结果。
无论如何,在我看来,您正在进入无用的过早优化。你确定你真的需要这样的效率吗?
【讨论】:
两者都不是“更有效”,没有上下文。
嵌套循环适用于任何城市列表,无论多大,只要您首先设法构建它。它有额外的额外开销,即运行一个反复重新初始化内循环的外循环。
第二个避免了这种情况,但必须构造所有数据''.join(cities) 的第二个副本以迭代。如果您的城市列表足够大,或者您的环境在内存上足够短,那么它会在第一个成功的地方失败。它还会产生更多需要回收的垃圾。
几乎可以肯定,任何一个都可以足够快地完成工作,除非您正在为 RAM 非常有限的豌豆脑嵌入式系统进行开发。一般来说,在具有 GHz CPU 和 GB RAM 的现代 PC 系统上,效率不应是您的首要考虑因素。一个例外是,您可以预测需要在 RAM 中组装的数据量有超过可用 RAM 量的危险,在这种情况下,避免完整的中间副本是值得的。另一个是你有不同顺序的算法,并且不能绝对保证数据量总是很小。在这种情况下,更喜欢低阶算法。当 N 变大时,O(N) 在很大程度上胜过 O(N^2)!
【讨论】:
这是您应该测试的第三个选项(速度取决于您的用例):
print '\n'.join(''.join(cities))
因为每次调用 print 都有相当多的开销,所以尽可能少地使用通常是好的(在这种情况下是一个)。
【讨论】:
@ronen-ness 已经有 a good answer 指出担心它是过早的微优化。
我想补充一点,在尝试使用 Python 计时代码时,最好的选择是使用 timeit 而不是编写自己的基本测试。
重写看起来像:
import timeit
method1 = '''
for c in cities:
for l in c:
pass
'''
method2 = '''
for l in ''.join(cities):
pass
'''
print(timeit.timeit(stmt=method1, setup="cities = ['Berlin','London','Chicago']", number=100000))
print(timeit.timeit(stmt=method2, setup="cities = ['Berlin','London','Chicago']", number=100000))
0.046141645999999994
0.04605432300000001
当我运行原始结果时,结果就像
method 1: 0.09271407127380371
method 2: 0.09324479103088379
由于 timeit 使用 Mac / Win / Linux 的正确时钟,计时结果要快得多,它会关闭垃圾收集并从测量中移除一堆其他开销。
但是 - 在 timeit 和原始版本中,数字变化很大。在我做的运行中,有时第一种方法更快,有时是第二种方法。这告诉我它们实际上是相同的。没有统计学上的显着差异。这些变化是由于机器上发生的其他事情造成的。
^相对而言,因为 100K 迭代的毫秒差异意味着每次迭代只有纳秒,这不值得你花时间。我已经花费了数十亿纳秒来写这篇文章。
【讨论】: