我一直在使用 Python 中的 map 函数,我正在寻找一些帮助来理解以下行为:
foo="12345"
print map(int,foo)
给你[1, 2, 3, 4, 5]
。显然int(foo)
是吐了出来12345
。那么究竟发生了什么?由于字符串可以按字符迭代,因此上述两行是否与
print [int(x) for x in foo]
我知道他们会输出相同的结果,但幕后有什么不同吗?一个比另一个更有效还是更好?还有一个“pythonic”吗?
非常感谢!
map()
在某些情况下可能比使用列表推导要快一些,在某些情况下 map 比列表推导慢。
使用内置函数时:
python -mtimeit -s'xs=xrange(1000)' 'map(int,"1234567890")'
10000 loops, best of 3: 18.3 usec per loop
python -mtimeit -s'xs=xrange(1000)' '[int(x) for x in "1234567890"]'
100000 loops, best of 3: 20 usec per loop
随着lambda
,map()
变慢:
python -mtimeit -s'xs=xrange(1000)' '[x*10 for x in "1234567890"]'
100000 loops, best of 3: 6.11 usec per loop
python -mtimeit -s'xs=xrange(1000)' 'map(lambda x:x*10,"1234567890")'
100000 loops, best of 3: 11.2 usec per loop
但是,在 python 3x 中map()
返回一个映射对象,即一个迭代器
将函数应用于可迭代的每个项目并返回结果列表。
int()
尝试将传递的内容转换为整数,ValueError
如果您尝试一些愚蠢的事情,则会引发 a ,如下所示:
>>> int('Hello')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'Hello'
map()
将返回一个列表,该列表具有您要求它调用任何可迭代的函数的返回值。如果您的函数没有返回任何内容,那么您将获得一个None
s 列表,如下所示:
>>> def silly(x):
... pass
...
>>> map(silly,'Hello')
[None, None, None, None, None]
这是执行以下操作的简短有效的方法:
def verbose_map(some_function,something):
results = []
for i in something:
results.append(some_function(i))
return results
map
可以认为是这样工作的:
def map(func, iterable):
answer = []
for elem in iterable:
answer.append(func(elem))
return answer
基本上,它返回一个列表L
,其中第 i 个元素是对可迭代的第 i 个元素L
进行计算的结果。func
因此,在 for 循环的每次迭代中,带有sint
的字符串int
,该元素是一个特定的字符,当给定它时,它int
会作为一个实际的int
. 调用map
此类字符串的结果是一个列表,其元素对应int
于字符串中相应字符的 ed 值。
所以是的,如果L = "12345"
, thenmap(int, L)
是同义词[int(x) for x in L]
希望这可以帮助
是的,幕后有很大的不同。如果你print(map)
会看到它是内置的。内置函数的执行速度比用 python 编写的或大多数基于语言解析方式的函数快,map 使用快速 iter 方法,而列表推导则没有。其他没有区别。
map(int, '1'*1000000)
对比
[int(i) for i in '1'*1000000]
使用 CPython 和 unix time 程序,map 在 ~3 秒内完成,列表理解在 ~5 秒内完成。
哦,需要注意的一件事,这只适用于传递给 map 的函数是用 C 语言编写的。
foo="12345"
In [507]: dis.dis('map(int,foo)')
0 <109> 28769
3 STORE_SLICE+0
4 LOAD_ATTR 29806 (29806)
7 <44>
8 BUILD_TUPLE 28527
11 STORE_SLICE+1
def map(func, iterable):
answer = []
for elem in iterable:
answer.append(func(elem))
return answer
dis.dis('map(int,foo)')
0 <109> 28769
3 STORE_SLICE+0
4 LOAD_ATTR 29806 (29806)
7 <44>
8 BUILD_TUPLE 28527
11 STORE_SLICE+1
dis.dis('[int(x) for x in foo]')
0 DELETE_NAME 28265 (28265)
3 LOAD_GLOBAL 30760 (30760)
6 STORE_SLICE+1
7 SLICE+2
8 BUILD_TUPLE 29295
11 SLICE+2
12 SETUP_LOOP 26912 (to 26927)
15 JUMP_FORWARD 26144 (to 26162)
18 JUMP_IF_FALSE 23919 (to 23940)
和时间:
In [512]: timeit map(int,foo)
100000 loops, best of 3: 6.89 us per loop
In [513]: def mymap(func, iterable):
...: answer = []
...: for elem in iterable:
...: answer.append(func(elem))
...: return answer
In [514]: timeit mymap(int,foo)
100000 loops, best of 3: 8.29 us per loop
In [515]: timeit [int(x) for x in foo]
100000 loops, best of 3: 7.5 us per loop
“更高效”是一罐蠕虫。在这台计算机上,将 map 与CPython一起使用会更快,但pypy的列表理解更快
$ python -mtimeit 'map(int,"1234567890")'
100000 loops, best of 3: 8.05 usec per loop
$ python -mtimeit '[int(x) for x in "1234567890"]'
100000 loops, best of 3: 9.33 usec per loop
$ pypy -mtimeit 'map(int,"1234567890")'
1000000 loops, best of 3: 1.18 usec per loop
$ pypy -mtimeit '[int(x) for x in "1234567890"]'
1000000 loops, best of 3: 0.938 usec per loop
即使需要额外的调用,Python3 也显示map()
得更快list()
$ python3 -mtimeit 'list(map(int,"1234567890"))'
100000 loops, best of 3: 11.8 usec per loop
$ python3 -mtimeit '[int(x) for x in "1234567890"]'
100000 loops, best of 3: 13.6 usec per loop