问题:获取map()以在Python 3.x中返回列表

我正在尝试将列表映射为十六进制,然后在其他地方使用该列表。在python 2.6中,这很简单:

答: Python 2.6:

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

但是,在Python 3.1中,以上代码返回一个map对象。

B: Python 3.1:

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

如何在Python 3.x上检索映射列表(如上面的A所示)?

另外,还有更好的方法吗?我的初始列表对象大约有45个项目,并且id喜欢将它们转换为十六进制。

I’m trying to map a list into hex, and then use the list elsewhere. In python 2.6, this was easy:

A: Python 2.6:

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

However, in Python 3.1, the above returns a map object.

B: Python 3.1:

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

How do I retrieve the mapped list (as in A above) on Python 3.x?

Alternatively, is there a better way of doing this? My initial list object has around 45 items and id like to convert them to hex.


回答 0

做这个:

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

在Python 3+中,许多迭代可迭代对象的进程本身都会返回迭代器。在大多数情况下,这最终会节省内存,并且应该使处理速度更快。

如果您要做的只是最终遍历此列表,则无需将其转换为列表,因为您仍然可以map像这样遍历该对象:

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

Do this:

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

In Python 3+, many processes that iterate over iterables return iterators themselves. In most cases, this ends up saving memory, and should make things go faster.

If all you’re going to do is iterate over this list eventually, there’s no need to even convert it to a list, because you can still iterate over the map object like so:

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

回答 1

Python 3.5的新功能:

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

多亏了其他拆包概述

更新

一直在寻找更短的途径,我发现这也行得通:

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

开箱也适用于元组。注意最后的逗号。这使其成为1个元素的元组。也就是说,它相当于(*map(chr, [66, 53, 0, 94]),)

它比带有方括号的版本短一个字符,但我认为最好写,因为您从星号-扩展语法开始,所以我觉得它比较软。:)

New and neat in Python 3.5:

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

Thanks to Additional Unpacking Generalizations

UPDATE

Always seeking for shorter ways, I discovered this one also works:

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

Unpacking works in tuples too. Note the comma at the end. This makes it a tuple of 1 element. That is, it’s equivalent to (*map(chr, [66, 53, 0, 94]),)

It’s shorter by only one char from the version with the list-brackets, but, in my opinion, better to write, because you start right ahead with the asterisk – the expansion syntax, so I feel it’s softer on the mind. :)


回答 2

您为什么不这样做:

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

这称为列表理解。您可以在Google上找到很多信息,但是这里是list comprehensions上的Python(2.6)文档的链接。不过,您可能对Python 3文档更感兴趣。

Why aren’t you doing this:

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

It’s called a list comprehension. You can find plenty of information on Google, but here’s the link to the Python (2.6) documentation on list comprehensions. You might be more interested in the Python 3 documenation, though.


回答 3

返回列表的地图功能具有保存键入的优点,尤其是在交互式会话期间。您可以定义返回列表的lmap函数(类似于python2的函数imap):

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

然后打电话 lmap而不是即可map完成工作:比 lmap(str, x)短5个字符(在这种情况下为30%),list(map(str, x))并且肯定比短[str(v) for v in x]。您也可以创建类似的功能filter

对原始问题有一条评论:

我建议重命名为Geting map()以返回Python 3. *中的列表,因为它适用于所有Python3版本。有没有办法做到这一点?– meawoppl 1月24日17:58

有可能做到这一点,但它是一个非常糟糕的主意。只是为了好玩,您可以(但不应)执行以下操作:

__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

List-returning map function has the advantage of saving typing, especially during interactive sessions. You can define lmap function (on the analogy of python2’s imap) that returns list:

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

Then calling lmap instead of map will do the job: lmap(str, x) is shorter by 5 characters (30% in this case) than list(map(str, x)) and is certainly shorter than [str(v) for v in x]. You may create similar functions for filter too.

There was a comment to the original question:

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

It is possible to do that, but it is a very bad idea. Just for fun, here’s how you may (but should not) do it:

__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

回答 4

我的旧注释转换为更好的可见性:为了更好地“更好地做到这一点” map,如果您的输入已知为ASCII序数,则通常可以更快地转换为bytesla bytes(list_of_ordinals).decode('ascii')。这样就可以得到一个str值,但是如果您需要a list来实现可变性或类似功能,则可以将其转换(并且转换速度仍然更快)。例如,在微ipython基准中转换45个输入:

>>> %%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,则最快的map解决方案会花费大约20%的时间;即使转换回列表,它仍然不到最快map解决方案的40%。批量转换通过bytesbytes.decode然后批量转换回以list节省大量工作,但是如上所述,仅当您所有的输入都是ASCII序号(或每个字符特定于区域设置编码的字节中的序号latin-1)时,该方法才有效。

Converting my old comment for better visibility: For a “better way to do this” without map entirely, if your inputs are known to be ASCII ordinals, it’s generally much faster to convert to bytes and decode, a la bytes(list_of_ordinals).decode('ascii'). That gets you a str of the values, but if you need a list for mutability or the like, you can just convert it (and it’s still faster). For example, in ipython microbenchmarks converting 45 inputs:

>>> %%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)

If you leave it as a str, it takes ~20% of the time of the fastest map solutions; even converting back to list it’s still less than 40% of the fastest map solution. Bulk convert via bytes and bytes.decode then bulk converting back to list saves a lot of work, but as noted, only works if all your inputs are ASCII ordinals (or ordinals in some one byte per character locale specific encoding, e.g. latin-1).


回答 5

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

map(func,* iterables)->地图对象创建一个迭代器,该迭代器使用每个可迭代对象的参数来计算函数。当最短的迭代次数用尽时停止。

“进行迭代”

表示它将返回迭代器。

“使用每个可迭代对象的参数来计算函数”

意味着迭代器的next()函数将为每个可迭代对象取一个值,并将每个值传递给该函数的一个位置参数。

因此,您可以从map()函数中获得一个迭代器,然后jsut将其传递给内置函数list()或使用列表推导。

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”

means it will return an iterator.

“that computes the function using arguments from each of the iterables”

means that the next() function of the iterator will take one value of each iterables and pass each of them to one positional parameter of the function.

So you get an iterator from the map() funtion and jsut pass it to the list() builtin function or use list comprehensions.


回答 6

除了上述答案外Python 3,我们还可以简单地listmapas中创建结果值a

li = []
for x in map(chr,[66,53,0,94]):
    li.append(x)

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

我们可以通过另一个例子来概括我被打动的情况,对地图的操作也可以像regex问题中一样的方式处理,我们可以编写函数以获取list要映射的项目并同时获取结果集。例如

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]

In addition to above answers in Python 3, we may simply create a list of result values from a map as

li = []
for x in map(chr,[66,53,0,94]):
    li.append(x)

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

We may generalize by another example where I was struck, operations on map can also be handled in similar fashion like in regex problem, we can write function to obtain list of items to map and get result set at the same time. Ex.

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]

回答 7

您可以尝试通过仅迭代对象中的每个项目并将其存储在另一个变量中来从地图对象获取列表。

a = map(chr, [66, 53, 0, 94])
b = [item for item in a]
print(b)
>>>['B', '5', '\x00', '^']

You can try getting a list from the map object by just iterating each item in the object and store it in a different variable.

a = map(chr, [66, 53, 0, 94])
b = [item for item in a]
print(b)
>>>['B', '5', '\x00', '^']

回答 8

使用python中的列表理解和基本的地图函数实用程序,还可以做到这一点:

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

Using list comprehension in python and basic map function utility, one can do this also:

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


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。