Получение карты () для возврата списка в Python 3.x

Я пытаюсь отобразить список в гекс, а затем использовать список в другом месте. В Python 2.6 это было легко:

A: Python 2.6:

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

Однако в Python 3.1 вышеприведенное возвращает объект карты.

B: Python 3.1:

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

Как мне получить сопоставленный список (как в A выше) на Python 3.x?

В качестве альтернативы, есть ли лучший способ сделать это? Мой первоначальный объект списка содержит около 45 элементов, и я хотел бы преобразовать их в гекс.

12 ответов

Решение

Сделай это:

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

В Python 3+ многие процессы, которые выполняют итерации, возвращают сами итераторы. В большинстве случаев это приводит к экономии памяти и должно ускорить процесс.

Если все, что вы собираетесь сделать, это в конечном итоге перебрать этот список, нет необходимости даже конвертировать его в список, потому что вы все еще можете перебирать map объект вроде так:

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

Новое и аккуратное в Python 3.5:

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

Благодаря дополнительным обобщениям распаковки

ОБНОВИТЬ

Всегда ища более короткие пути, я обнаружил, что этот тоже работает:

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

Распаковка тоже работает в кортежах. Обратите внимание на запятую в конце. Это делает его кортежем из 1 элемента. То есть это эквивалентно (*map(chr, [66, 53, 0, 94]),)

Он короче всего на один символ из версии со списочными скобками, но, на мой взгляд, лучше написать, потому что вы начинаете прямо со звездочки - синтаксиса расширения, так что я чувствую, что это мягче на уме.:)

Почему ты не делаешь это:

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

Это называется пониманием списка. Вы можете найти много информации в Google, но вот ссылка на документацию по Python (2.6) по спискам. Возможно, вас больше заинтересует документация по Python 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 тоже.

Был комментарий к оригинальному вопросу:

Я бы предложил переименовать в Getting map(), чтобы получить список в Python 3.*, так как он применяется ко всем версиям Python3. Есть ли способ сделать это? - Meawoppl 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

Я не знаком с Python 3.1, но будет ли это работать?

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

Преобразование моего старого комментария для лучшей наглядности: для "лучшего способа сделать это" без map в целом, если известно, что ваши входные данные являются порядковыми числами ASCII, обычно их гораздо быстрее преобразовать в bytes и декодировать, а-ля bytes(list_of_ordinals).decode('ascii'), Это дает вам str значений, но если вам нужно 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, это занимает ~20% времени самого быстрого map решения; даже если вернуться к списку, это все равно менее 40% самых быстрых map решение. Массовое преобразование через bytes а также bytes.decode затем массовое преобразование обратно в list экономит много работы, но, как уже было отмечено, работает, только если все ваши входные данные являются ASCII-ординалами (или порядковыми числами в несколько байтов на кодировку, специфичную для локали символа, например latin-1).

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

map(func, *iterables) -> объект карты Создайте итератор, который вычисляет функцию, используя аргументы из каждого из итераций. Останавливается, когда самая короткая итерация исчерпана.

"Сделай итератор"

означает, что он вернет итератор.

"который вычисляет функцию, используя аргументы из каждого из итераций"

означает, что функция next() итератора примет одно значение каждого итерируемого элемента и передаст каждое из них одному позиционному параметру функции.

Таким образом, вы получаете итератор из функции map() и передаете его во встроенную функцию list() или используете списки.

В дополнение к вышеупомянутым ответам в Python 3мы можем просто создать list значений результата из map как

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

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

Мы можем обобщить на другом примере, где меня поразили, операции с картой также могут выполняться аналогично regex проблема, мы можем написать функцию для получения list элементов для сопоставления и получения результатов одновременно. 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]

Используя понимание списка в python и утилиту основных функций карты, можно также сделать это:

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

Лучший способ сделать это в pyton3.X

Просто вы можете сделать это в одной строке

      #Devil
input_list = [66, 53, 0, 94]
out = [chr(x) for x in input_list]
print(out)

# you will get the desire output in out list
# ['B', '5', '\x00', '^']

#------------------------------
#To retrieve your list use 'ord'

original_list = [ord(x) for x in out]
print(original_list )
#[66, 53, 0, 94]

Другой вариант - создать ярлык, возвращающий список:

from functools import reduce
_compose = lambda f, g: lambda *args: f(g(*args))
lmap = reduce(_compose, (list, map))

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

Вы можете попробовать получить список из объекта карты, просто перебирая каждый элемент в объекте и сохраняя его в другой переменной.

a = map(chr, [66, 53, 0, 94])
b = [item for item in a]
print(b)
>>>['B', '5', '\x00', '^']
Другие вопросы по тегам