获取map()以返回python 3.x中的列表

Getting a map() to return a list in Python 3.x

我正在尝试将列表映射为十六进制,然后在其他地方使用该列表。在Python2.6中,这很容易:

答:Python 2.6:

1
2
>>> map(chr, [66, 53, 0, 94])
['B', '5', '\x00', '^']

但是,在python 3.1中,上面的返回一个map对象。

B:Python 3.1:

1
2
>>> map(chr, [66, 53, 0, 94])
<map object at 0x00AF5570>

如何在python 3.x上检索映射列表(如上所述)?

或者,是否有更好的方法来实现这一点?我的初始列表对象有大约45个项目,我想把它们转换成十六进制。


这样做:

1
list(map(chr,[66,53,0,94]))

在python 3+中,许多迭代iterables的进程本身返回迭代器。在大多数情况下,这最终会节省内存,并且会使事情发展得更快。

如果您所要做的就是最终对这个列表进行迭代,那么甚至不需要将它转换为列表,因为您仍然可以像这样对map对象进行迭代:

1
2
3
# Prints"ABCD"
for ch in map(chr,[65,66,67,68]):
    print(ch)


你为什么不这样做:

1
[chr(x) for x in [66,53,0,94]]

这叫做列表理解。您可以在Google上找到很多信息,但这里有关于列表理解的python(2.6)文档的链接。不过,您可能对python 3文档更感兴趣。


python 3.5中的新的和整洁的:

1
[*map(chr, [66, 53, 0, 94])]

由于额外的解包归纳

更新

我一直在寻找较短的方法,发现这一方法也有效:

1
*map(chr, [66, 53, 0, 94]),

解包也可以用元组进行。注意末尾的逗号。这使它成为一个由1个元素组成的元组。也就是说,它相当于(*map(chr, [66, 53, 0, 94]),)

它比带括号的版本短了一个字符,但在我看来,最好还是写下来,因为你从前面的星号开始——扩展语法,所以我觉得它在心里更柔和。:)


列表返回映射函数具有保存键入的优点,特别是在交互式会话中。您可以定义返回列表的lmap函数(与python2的imap类似):

1
lmap = lambda func, *iterable: list(map(func, *iterable))

然后调用lmap而不是map来完成这项工作:lmap(str, x)list(map(str, x))短5个字符(本例为30%),当然也比[str(v) for v in x]短。您也可以为filter创建类似的函数。

对最初的问题有一个评论:

I would suggest a rename to Getting map() to return a list in Python 3.* as it applies to all Python3 versions. Is there a way to do this? – meawoppl Jan 24 at 17:58

这是可能的,但这是一个非常坏的主意。只是为了好玩,你可以(但不应该)这样做:

1
2
3
4
5
6
7
__global_map = map #keep reference to the original map
lmap = lambda func, *iterable: list(__global_map(func, *iterable)) # using"map" here will cause infinite recursion
map = lmap
x = [1, 2, 3]
map(str, x) #test
map = __global_map #restore the original map and don't do that again
map(str, x) #iterator

我不熟悉python 3.1,但是这行吗?

1
[chr(x) for x in [66, 53, 0, 94]]

将我以前的评论转换为更好的可见性:为了在不完全使用map的情况下"更好地做到这一点",如果知道您的输入是ASCII序列,那么转换为bytes并解码为la bytes(list_of_ordinals).decode('ascii')通常要快得多。这使你得到一个str值,但是如果你需要一个list的可变性或类似的,你可以转换它(它仍然更快)。例如,在ipython微基准转换45个输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> %%timeit -r5 ordinals = list(range(45))
... list(map(chr, ordinals))
...
3.91 μs ± 60.2 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... [*map(chr, ordinals)]
...
3.84 μs ± 219 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... [*bytes(ordinals).decode('ascii')]
...
1.43 μs ± 49.7 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... bytes(ordinals).decode('ascii')
...
781 ns ± 15.9 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each)

如果您将其保留为str,则需要20%的最快map解决方案的时间;即使将其转换回列表,它仍不到40%的最快map解决方案。通过bytesbytes.decode进行大容量转换,然后大容量转换回list可节省大量工作,但如前所述,只有当所有输入都是ASCII序数(或每个字符一个字节的特定区域编码的序数,如latin-1时,才能工作。


使用python中的列表理解和基本的map函数实用程序,您也可以这样做:

chi = [x for x in map(chr,[66,53,0,94])]


除了上述在Python 3中的答案外,我们可以简单地从map中创建一个list结果值作为

1
2
3
4
5
6
li = []
for x in map(chr,[66,53,0,94]):
    li.append(x)

print (li)
>>>['B', '5', '\x00', '^']

我们可以用另一个例子来概括我被击中的地方,地图上的操作也可以用类似于regex问题的方式来处理,我们可以编写函数来获得list个要映射的项,同时得到结果集。前任。

1
2
3
4
5
6
7
b = 'Strings: 1,072, Another String: 474 '
li = []
for x in map(int,map(int, re.findall('\d+', b))):
    li.append(x)

print (li)
>>>[1, 72, 474]


1
list(map(chr, [66, 53, 0, 94]))

map(func, *iterables) --> map object
Make an iterator that computes the function using arguments from
each of the iterables. Stops when the shortest iterable is exhausted.

"Make an iterator"

意味着它将返回迭代器。

"that computes the function using arguments from each of the iterables"

意味着迭代器的next()函数将获取每个iterables的一个值,并将每个iterables传递给函数的一个位置参数。

所以从map()函数中得到一个迭代器,jsut将它传递给list()内置函数或使用list理解。