我们假设我有一个清单:
cities = ['Berlin','London','Chicago']
我想单独打印该列表中的每个字母。
这些方法中的任何一种更有效还是推荐?
这:
for c in cities:
for l in c:
print l
或者这个:
for l in ''.join(cities):
print l
答案 0 :(得分:4)
"什么会更有效率"通常取决于操作系统和其他因素。但是,你可以做一个非常简单的基准测试:
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
我相信大多数系统都会有类似的结果。
无论如何,听起来像你正在进入无用的过早优化。你确定你真的需要那么高的效率吗?
答案 1 :(得分:1)
没有上下文,“效率更高”。
嵌套循环可以在任何城市列表上工作,无论多大,只要你设法在第一时间构建它。它具有运行外部循环的额外开销,该循环重复地重新初始化内部循环。
第二个避免这种情况,但必须构建所有数据''.join(cities)
的第二个副本以进行迭代。如果您的城市列表足够大或者您的环境在内存上足够短,那么在第一个城市成功的地方就会失败。它还会产生更多需要回收的垃圾。
除非你正在开发一个RAM非常有限的豌豆脑嵌入式系统,否则几乎可以肯定要么足够快地完成工作。一般而言,在具有GHz CPU和Gbytes RAM的现代PC系统中,效率不应该是您首要考虑的因素。一个例外是,您可以预测在RAM中组装所需的数据量有超出可用RAM量的危险,在这种情况下,避免使用完整的中间副本是值得的。另一个是你有不同顺序的算法,不能绝对保证数据量总是保持很小。在那种情况下,更喜欢低阶算法。当N变大时,O(N)在很大程度上胜过O(N ^ 2)!
答案 2 :(得分:1)
这是您应该测试的第三个选项(速度取决于您的使用案例):
print '\n'.join(''.join(cities))
因为每次打印调用都有相当多的开销,所以通常使用尽可能少(在这种情况下为1)。
答案 3 :(得分:0)
@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 和 original 中,数字变化很大。在我所做的运行中,有时第一种方法更快,有时是第二种方法。这告诉我它们实际上是相同的;没有统计学上的显着差异。变化将是由于机器上发生的其他事情。
^相对而言,因为 100K 迭代的毫秒差异意味着每次迭代需要纳秒,这不值得您花时间。我花了几十亿纳秒才写这个。