$ python -m timeit -s'xs=range(10)' 'map(hex, xs)'100000 loops, best of 3: 4.86 usec per loop$ python -m timeit -s'xs=range(10)' '[hex(x) for x in xs]'100000 loops, best of 3: 5.58 usec per loop
当map需要lambda时,性能比较如何完全颠倒的示例:
$ python -m timeit -s'xs=range(10)' 'map(lambda x: x+2, xs)'100000 loops, best of 3: 4.24 usec per loop$ python -m timeit -s'xs=range(10)' '[x+2 for x in xs]'100000 loops, best of 3: 2.32 usec per loop
不太常见的病例:但是如果你是map(sum, myLists)0,使用map通常是合理的,尽管它被认为是“unpythonic”。例如,map(sum, myLists)比[sum(x) for x in myLists]更优雅/简洁。你获得了不必组成虚拟变量(例如sum(x) for x...或sum(_) for _...或sum(readableName) for readableName...)的优雅,这些变量你必须输入两次,只是为了迭代。同样的论点适用于filter和reduce以及itertools模块中的任何东西:如果你已经手头有一个函数,你可以继续做一些函数式编程。这在某些情况下会获得易读性,而在其他情况下会失去易读性(例如,新手程序员,多个参数)……但无论如何,代码的易读性在很大程度上取决于您的注释。
>>> (str(n) for n in range(10**100))<generator object <genexpr> at 0xacbdef>
您基本上可以将[...]语法视为将生成器表达式传递给列表构造函数,例如list(x for x in range(5))。
简单的例子
from operator import negprint({x:x**2 for x in map(neg,range(5))})
print({x:x**2 for x in [-y for y in range(5)]})
print({x:x**2 for x in (-y for y in range(5))})
列表推导不是惰性的,所以可能需要更多的内存(除非你使用生成器推导)。方括号[...]通常会让事情变得明显,尤其是在一堆括号中时。另一方面,有时你会像输入[x for x in...一样冗长。只要你保持迭代器变量的简短,如果你不缩进代码,列表推导通常会更清晰。但你总是可以缩进代码。
print({x:x**2 for x in (-y for y in range(5))})
或者把事情搞砸:
rangeNeg5 = (-y for y in range(5))print({x:x**2 for x in rangeNeg5})
python3效率对比
map现在是懒惰的:
% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=map(f,xs)'1000000 loops, best of 3: 0.336 usec per loop ^^^^^^^^^
% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=list(map(f,xs))'10000 loops, best of 3: 165/124/135 usec per loop ^^^^^^^^^^^^^^^for list(<map object>)
% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=[f(x) for x in xs]'10000 loops, best of 3: 181/118/123 usec per loop ^^^^^^^^^^^^^^^^^^for list(<generator>), probably optimized
% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=list(f(x) for x in xs)'1000 loops, best of 3: 215/150/150 usec per loop ^^^^^^^^^^^^^^^^^^^^^^for list(<generator>)
x_list = [(i, i+1, i+2, i*2, i-9) for i in range(1000)]i_list = list(range(1000))
内置功能:
%timeit map(sum, x_list) # creating iterator object# Output: The slowest run took 9.91 times longer than the fastest.# This could mean that an intermediate result is being cached.# 1000000 loops, best of 3: 277 ns per loop
%timeit list(map(sum, x_list)) # creating list with map# Output: 1000 loops, best of 3: 214 µs per loop
%timeit [sum(x) for x in x_list] # creating list with list comprehension# Output: 1000 loops, best of 3: 290 µs per loop
lambda函数:
%timeit map(lambda i: i+1, i_list)# Output: The slowest run took 8.64 times longer than the fastest.# This could mean that an intermediate result is being cached.# 1000000 loops, best of 3: 325 ns per loop
%timeit list(map(lambda i: i+1, i_list))# Output: 1000 loops, best of 3: 183 µs per loop
%timeit [i+1 for i in i_list]# Output: 10000 loops, best of 3: 84.2 µs per loop
%timeit (sum(i) for i in x_list)# Output: The slowest run took 6.66 times longer than the fastest.# This could mean that an intermediate result is being cached.# 1000000 loops, best of 3: 495 ns per loop
%timeit list((sum(x) for x in x_list))# Output: 1000 loops, best of 3: 319 µs per loop
%timeit (i+1 for i in i_list)# Output: The slowest run took 6.83 times longer than the fastest.# This could mean that an intermediate result is being cached.# 1000000 loops, best of 3: 506 ns per loop
%timeit list((i+1 for i in i_list))# Output: 10000 loops, best of 3: 125 µs per loop
In [1]: odd_cubes = [x ** 3 for x in range(10) if x % 2 == 1] # using a list comprehension
In [2]: odd_cubes_alt = list(map(lambda x: x ** 3, filter(lambda x: x % 2 == 1, range(10)))) # using map and filter
In [3]: odd_cubes == odd_cubes_altOut[3]: True
python -mtimeit -s "xs=range(123456)" "map(hex, xs)"1000000 loops, best of 5: 218 nsec per looppython -mtimeit -s "xs=range(123456)" "[hex(x) for x in xs]"10 loops, best of 5: 19.4 msec per loop
import perfplot
def standalone_map(data):return map(hex, data)
def list_map(data):return list(map(hex, data))
def comprehension(data):return [hex(x) for x in data]
b = perfplot.bench(setup=lambda n: list(range(n)),kernels=[standalone_map, list_map, comprehension],n_range=[2 ** k for k in range(20)],equality_check=None,)b.save("out.png")b.show()
import perfplotimport numpy as np
def standalone_map(data):return map(lambda x: x ** 2, data[0])
def list_map(data):return list(map(lambda x: x ** 2, data[0]))
def comprehension(data):return [x ** 2 for x in data[0]]
def numpy_asarray(data):return np.asarray(data[0]) ** 2
def numpy_direct(data):return data[1] ** 2
b = perfplot.bench(setup=lambda n: (list(range(n)), np.arange(n)),kernels=[standalone_map, list_map, comprehension, numpy_direct, numpy_asarray],n_range=[2 ** k for k in range(20)],equality_check=None,)b.save("out2.png")b.show()