2009-08-20 7 views
302

Próbuję odwzorować listę na heks, a następnie użyć jej w innym miejscu. W pytona 2.6, było proste:Uzyskiwanie mapy() w celu zwrócenia listy w języku Python 3.x

A: Python 2.6:

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

Jednakże Pythona 3.1, powyżej zwraca obiekt mapy.

B: Python 3.1:

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

Jak mogę odzyskać odwzorowaną listy (jak w powyżej) w Pythonie 3.x?

Czy istnieje lepszy sposób na zrobienie tego? Mój początkowy obiekt listy ma około 45 elementów i id lubisz je konwertować na hex.

+0

@meawoppl zobacz moją odpowiedź poniżej http://stackoverflow.com/a/24507069/17523 –

Odpowiedz

462

Wykonaj:

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

w Pythonie 3+, wiele procesów, które iteracyjnego iterables powrócić samych iteratorów. W większości przypadków kończy się to oszczędzaniem pamięci i powinno przyspieszyć działanie.

Jeśli wszystko masz zamiar zrobić to iterować tej liście ostatecznie, nie ma potrzeby nawet przekonwertować go na liście, ponieważ nadal można iteracyjne nad obiektem map tak:

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

Dziękuję za wspaniałe wyjaśnienie !! – mozami

+10

Oczywiście, możesz również iterować nad tym: (chr (x) dla x w [65,66,67,68]). To nawet nie wymaga mapy. – hughdbrown

+0

@hughdbrown Argument za używaniem 3."Mapa" 1 będzie leniwą oceną podczas iteracji złożonej funkcji, dużych zestawów danych lub strumieni. –

70

Dlaczego to robisz:

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

To się nazywa listowego. Możesz znaleźć wiele informacji na temat Google, ale here's the link to the Python (2.6) documentation on list comprehensions. Być może jednak bardziej interesuje Cię the Python 3 documenation.

+8

Tak, aby wyświetlić listę. – hughdbrown

+4

Hmmmm. Być może musi być ogólne ogłaszanie na listach, generatory, map(), zip() i wiele innych szybkich dobroci iteracyjnych w pythonie. – hughdbrown

+23

Chyba dlatego, że jest bardziej gadatliwy, musisz napisać dodatkową zmienną (dwa razy) ... Jeśli operacja jest bardziej złożona i kończysz pisanie lambda, lub musisz też upuścić pewne elementy, myślę, że zrozumienie jest definitywnie lepiej niż mapa + filtr, ale jeśli masz już funkcję, którą chcesz zastosować, mapa jest bardziej zwięzła. – fortran

11

I nie znasz Pythona 3.1, ale czy to zadziała?

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

działa idealnie. – ExceptionSlayer

18

Funkcja powrotu do listy ma tę zaletę, że oszczędza pisanie, szczególnie podczas sesji interaktywnych. Można zdefiniować lmap funkcję (na analogii python2 na imap), która zwraca listę:

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

Potem dzwoni lmap zamiast map będzie wykonać zadanie: lmap(str, x) jest krótszy o 5 znaków (30% w tym przypadku) niż list(map(str, x)) i jest z pewnością krótszy niż [str(v) for v in x]. Możesz także utworzyć podobne funkcje dla filter.

Było komentarz do pierwotnego pytania:

Proponuję zmienić nazwę Uzyskiwanie mapę(), aby powrócić do listy w Pythonie 3. *, ponieważ odnosi się do wszystkich wersji Python3. Czy jest jakiś sposób na zrobienie tego? - meawoppl 24 stycznia o 17:58

To jest możliwe, aby to zrobić, ale jest to bardzo zły pomysł.Tak dla zabawy, oto jak możesz (ale nie należy) zrobić:

__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 
43

Nowe i schludny w Pythonie 3.5:

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

Dzięki Additional Unpacking Generalizations

+6

Co jest nie tak z 'list()'? – Quelklef

+2

@Quelklef 'list()' nie wygląda tak schludnie – Arijoon

+1

@Quelklef: Również podejście rozpakowywania jest trywialnie szybsze dzięki temu, że nie trzeba szukać konstruktora 'list' i wywoływać ogólnych mechanizmów wywoływania funkcji. Długie wejście nie ma znaczenia; na krótką, może to zrobić dużą różnicę. Używając powyższego kodu z danymi wejściowymi jako 'krotką', więc nie jest ona wielokrotnie odtwarzana, mikroprocesory' ipython' pokazują, że podejście 'list()' owijania trwa około 20% dłużej niż rozpakowywanie. Pamiętajcie, w kategoriach bezwzględnych, mówimy o 150 ns, co jest trywialne, ale macie pomysł. – ShadowRanger

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

map (func, * iterables) -> obiekt mapy Utwórz iterator, który oblicza funkcję śpiewaj argumenty od z każdej iteracji. Zatrzymuje się, gdy najkrótsza liczba iteracji zostanie wyczerpana.

"Złóż iterator"

oznacza powróci iterator.

„który oblicza funkcję używając argumentów z każdej iterables”

oznacza, że ​​next() funkcja iteratora zajmie jedną wartość każdego iterables i przekazać każdy z nich do jednego pozycyjnego parametr funkcji.

Dostajemy więc iterator z funkcji map() i jsut przekazujemy go do wbudowanej funkcji list() lub korzystania z listy.

1

Konwersja my old comment dla lepszej widoczności: na „lepszy sposób to zrobić” bez map całkowicie, jeśli wejścia są znane jako porządkowe ASCII, to na ogół znacznie szybciej konwertować do bytes i dekodowania, a la bytes(list_of_ordinals).decode('ascii'). To daje ci str z wartości, ale jeśli potrzebujesz list dla zmienności lub podobnego, możesz po prostu go przekonwertować (i jest jeszcze szybszy). Na przykład, w ipython microbenchmarks konwersji 45 wejść:

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

Jeśli zostawisz go jako str, trwa ~ 20% czasu z najszybszych map rozwiązań; nawet konwertując z powrotem na listę, wciąż jest mniej niż 40% najszybszego rozwiązania map. Masowych konwersji poprzez bytes i bytes.decode następnie zbiorczo Nawrócenie list oszczędza wiele pracy, ale Jak już wspomniano, działa tylko jeśli wszystkie wejścia są porządkowe ASCII (lub porządkowe w jakiś jeden bajt za kodowania określonego locale charakter, np latin-1).