Harita işlevini anlama


311
map(function, iterable, ...)

Fonksiyonu yinelenebilir öğelerin her birine uygulayın ve sonuçların bir listesini döndürün. Ek yinelenebilir argümanlar iletilirse, işlev bu kadar çok argümanı almalı ve tüm yinelenebilir öğelerdeki öğelere paralel olarak uygulanmalıdır.

Bir yinelenebilir diğerinden daha kısaysa, Hiçbiri öğelerle genişletildiği varsayılır.

İşlev ise None, kimlik işlevi varsayılır; birden fazla bağımsız değişken varsa map(), tüm yinelenebilir öğelerden (bir tür transpoze işlemi) karşılık gelen öğeleri içeren gruplardan oluşan bir liste döndürür.

Yinelenebilir argümanlar bir dizi veya yinelenebilir herhangi bir nesne olabilir; sonuç her zaman bir listedir.

Bunun Kartezyen bir ürün yapımında rolü nedir?

content = map(tuple, array)

Orada herhangi bir yere bir demet koymak ne gibi bir etkiye sahiptir? Ayrıca harita fonksiyonu olmadan çıkışın abcve onunla birlikte olduğunu fark ettim a, b, c.

Bu işlevi tam olarak anlamak istiyorum. Referans tanımlarını da anlamak zordur. Çok süslü tüy.


2
Aslında neyi başarmak istiyorsunuz ve neden özel olarak kullanmak istiyorsunuz map?
Kris Harper

3
@WebMaster evet, yapıştırdığınız belgelerin ilk cümlesine göre - "Yinelenebilir her öğeye işlev uygula". Paragrafın geri kalanı daha karmaşık vakalarla ilgilidir - olduğu gibi map(None, a, b, c)çıkıyor zip(a, b, c). Ancak uygulamada bunun çok nadir olduğunu görürsünüz, çünkü tam olarak zipçağrı eşdeğerdir.
lvc

9
Python öğrenmek için çok uğraşıyorum ve python.org'da bir tanım açtığımda. ilk cümleden sonra hiçbir şey anlamıyorum. Peki. teşekkür ederim.
Web Master

2
tuplebir yinelemeyi alan ve aynı öğelere sahip bir demet veren - yani tuple([1, 2, 3])eşdeğerdir (1, 2, 3). Çünkü map(tuple, array), arrayyinelenebilir bir yinelenebilir olurdu (bir liste listesi düşünün) ve size bir iç kısma dönüşen her iç listeyi geri verir.
lvc

1
Genel olarak, en önemli olan herhangi bir işlevin belgelerinin ilk cümlesidir. Bunu anlarsanız, onun özünü elde edersiniz. Geri kalanı ayrıntılı olarak davranışlarını belirtir ve bunun bazı edecektir başlamak biraz opak ve size görmeden önce ona dayanan garip bir deyim rastlamak gerekebilir "Ah, bu araçlar ne anlama!". Ancak, birkaç yerleşik için bu ampul anını aldığınızda, belgeleri biraz daha kolay anlamaya başlamalısınız.
lvc

Yanıtlar:


441

mapözellikle pitonik değil. Bunun yerine liste anlayışlarını kullanmanızı tavsiye ederim:

map(f, iterable)

temel olarak şuna eşittir:

[f(x) for x in iterable]

mapkendi başına bir Kartezyen ürün yapamaz, çünkü çıktı listesinin uzunluğu her zaman giriş listesiyle aynıdır. Gerçi bir liste anlayışı ile kartezyen bir ürün yapabilirsiniz:

[(a, b) for a in iterable_a for b in iterable_b]

Sözdizimi biraz kafa karıştırıcı - temel olarak şuna eşdeğer:

result = []
for a in iterable_a:
    for b in iterable_b:
        result.append((a, b))

36
mapEn azından gösterdiğiniz durumda, liste kavrayışlarından çok daha az ayrıntılı kullanıyorum .
marbel

1
Haritayı özellikler için nasıl kullanırım? -Ne mapeşdeğer nedir [v.__name__ for v in (object, str)]?
A Sz

@ASz Nasıl olur map(lambda v: v.__name__, list)?
Kilian

10
harita fonksiyonlarını çağırarak .. hızlı o Yineleyicilerin uzunluğuna dayalı işlevleri çağırmak olmadığından olduğu sahiptir havai .. İzle 06:00 youtube.com/watch?v=SiXyyOA6RZg&t=813s
Anati

1
Düşündüm @anati mapoldu bazen hızlı comprehensions daha bazen değil, kesin çünkü işlev çağrısı yükü? Özellikle, öğrendiğim buluşsal yöntem, kullanırken mapekstra fonksiyon çağrısı yapmanızı gerektirdiğinde, kavrayışın daha hızlı olduğu yönündedir. Örneğin ben inanmak önderlik etti map(lambda foo: foo.bar, my_list)daha yavaştır foo.bar for foo in my_listve bu da map(operator.add, my_list_of_pairs)daha yavaş olduğu x + y for x, y in my_list_of_pairskesin çünkü ek işlev çağrısı.
mtraceur

86

mapFonksiyonel programlama konusunda bilgili birisinin, kullanarak bir tane oluşturmanın yolunu anlamanın imkansız olabileceğini hayal etsem de, bir Kartezyen ürünle hiç ilgili değildir map.

map Python 3'te buna eşdeğerdir:

def map(func, iterable):
    for i in iterable:
        yield func(i)

ve Python 2'deki tek fark, yielding yerine bir kerede geri dönmek için sonuçların tam bir listesini oluşturmasıdır .

Her ne kadar Python kuralı, genellikle mapilk argüman olarak lambda ifadesi kullanıyorsanız, çağrı ile aynı sonucu elde etmek için genellikle liste kavrayışlarını (veya jeneratör ifadelerini) tercih etse de:

[func(i) for i in iterable]

"Dizgiyi bir diziye dönüştür" sorusundaki yorumlarda ne istediğine bir örnek olarak, "dizi" ile muhtemelen bir dizi veya bir liste istersiniz (her ikisi de diğer dillerden diziler gibi biraz davranır) -

 >>> a = "hello, world"
 >>> list(a)
['h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd']
>>> tuple(a)
('h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd')

mapBurada bir kullanım, tek bir dize yerine dizelerin bir listesiylemap başlarsanız, hepsini tek tek listeleyebilir:

>>> a = ["foo", "bar", "baz"]
>>> list(map(list, a))
[['f', 'o', 'o'], ['b', 'a', 'r'], ['b', 'a', 'z']]

map(list, a)Python 2'de eşdeğer olduğunu unutmayın , ancak Python 3'te listbir fordöngüye beslemek dışında bir şey yapmak istiyorsanız (veya sumbir diziye değil, yalnızca tekrarlanabilir bir işleme işlevine sahip olmak istiyorsanız) aramaya ihtiyacınız olduğunu unutmayın . Ancak, bir liste kavrayışının genellikle tercih edildiğini de unutmayın:

>>> [list(b) for b in a]
[['f', 'o', 'o'], ['b', 'a', 'r'], ['b', 'a', 'z']]

haritası (eğlence x -> (x, x)) anlaşılması zor görünmüyor ... (haritadan gerçek bir kartezyen ürün elde etmek imkansız olurdu, haritanın ürettiği her şey her zaman bir liste biçimidir)
Kristopher Micinski

36

map kaynağın her öğesine bir işlev uygulayarak yeni bir liste oluşturur:

xs = [1, 2, 3]

# all of those are equivalent — the output is [2, 4, 6]
# 1. map
ys = map(lambda x: x * 2, xs)
# 2. list comprehension
ys = [x * 2 for x in xs]
# 3. explicit loop
ys = []
for x in xs:
    ys.append(x * 2)

n-ary map, yinelenen giriş yinelenebilirlerini birleştirmeye ve daha sonra bu sıkıştırılmış listenin her öğesine dönüştürme işlevini uygulamaya eşdeğerdir. Bu var olmayan bir Kartezyen ürün:

xs = [1, 2, 3]
ys = [2, 4, 6]

def f(x, y):
    return (x * 2, y // 2)

# output: [(2, 1), (4, 2), (6, 3)]
# 1. map
zs = map(f, xs, ys)
# 2. list comp
zs = [f(x, y) for x, y in zip(xs, ys)]
# 3. explicit loop
zs = []
for x, y in zip(xs, ys):
    zs.append(f(x, y))

zipBurada kullandım , ancak mapyinelenebilirler aynı boyutta olmadığında davranış aslında biraz farklı - belgelerinde belirtildiği gibi, yinelenebilirleri içerecek şekilde genişletiyor None.


1
karmaşık, bu gönderiyi sindirmeye çalışıyor
Web Master

1
@WebMaster Bu konuda karmaşık olan nedir?
Jossie Calderon

Bence en iyi cevap. Örnekte lambda'yı işlev olarak kullanmak bunu çok açık hale getirir.
sheldonzy

Ne yazık ki bunların hepsi eşdeğer değildir - çıktı, [2,4,6]liste kavrama ve açık döngüler içindir, ancak harita bir harita nesnesi döndürür - örneğin bunu alıyorum: <map at 0x123a49978>Sonra bir listeye zorlamak zorundayım.
leerssej

20

Biraz basitleştirmek gerekirse, map()böyle bir şey yaptığınızı hayal edebilirsiniz :

def mymap(func, lst):
    result = []
    for e in lst:
        result.append(func(e))
    return result

Gördüğünüz gibi, bir işlev ve bir liste alır ve işlevi giriş listesindeki öğelerin her birine uygulama sonucunda yeni bir liste döndürür. Ben gerçeklik çünkü "biraz basitleştirerek" dedi map()işleyebilir birden fazla iterable:

Ek yinelenebilir argümanlar iletilirse, işlev bu kadar çok argümanı almalı ve tüm yinelenebilir öğelerdeki öğelere paralel olarak uygulanmalıdır. Bir yinelenebilir diğerinden daha kısaysa, Hiçbiri öğelerle genişletildiği varsayılır.

Sorunun ikinci kısmı için: Kartezyen bir ürün yapımında bu nasıl bir rol oynuyor? iyi, map() böyle bir listenin kartezyen ürününü oluşturmak için kullanılabilir:

lst = [1, 2, 3, 4, 5]

from operator import add
reduce(add, map(lambda i: map(lambda j: (i, j), lst), lst))

... Ama gerçeği söylemek gerekirse product(), sorunu çözmek için çok daha basit ve doğal bir yol var:

from itertools import product
list(product(lst, lst))

Her iki durumda da, sonuç lstyukarıda tanımlandığı gibi kartezyen ürünüdür :

[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5),
 (2, 1), (2, 2), (2, 3), (2, 4), (2, 5),
 (3, 1), (3, 2), (3, 3), (3, 4), (3, 5),
 (4, 1), (4, 2), (4, 3), (4, 4), (4, 5),
 (5, 1), (5, 2), (5, 3), (5, 4), (5, 5)]

17

map()Fonksiyon listeleri, jeneratörler, dizeleri ve diğer şeyler gibi, bir iterable veri yapısında her öğeye aynı prosedürü uygulamak için vardır.

Bir örneğe bakalım: map()bir listedeki her öğeyi tekrarlayabilir ve her öğeye yeni listeyi döndüreceğinden (size geri verir) bir işlev uygulayabilir.

Bir sayı alan, bu sayıya 1 ekleyen ve döndüren bir fonksiyonunuz olduğunu düşünün:

def add_one(num):
  new_num = num + 1
  return new_num

Ayrıca bir numara listeniz var:

my_list = [1, 3, 6, 7, 8, 10]

listedeki her sayıyı artırmak istiyorsanız, aşağıdakileri yapabilirsiniz:

>>> map(add_one, my_list)
[2, 4, 7, 8, 9, 11]

Not: En azından map()iki argümana ihtiyaç vardır. İlk olarak bir işlev adı ve ikinci olarak liste gibi bir şey.

Bakalım başka harika şeyler map()yapabilir. map()birden çok yinelenebilir (liste, dize vb.) alabilir ve her yinelenebilir öğeden bir öğeyi bağımsız değişken olarak bir işleve geçirebilir.

Üç listemiz var:

list_one = [1, 2, 3, 4, 5]
list_two = [11, 12, 13, 14, 15]
list_three = [21, 22, 23, 24, 25]

map() sizi belirli bir dizindeki öğelerin eklenmesini içeren yeni bir liste yapabilir.

Şimdi hatırlayın map(), bir işleve ihtiyacı var. Bu sefer yerleşik sum()işlevi kullanacağız . Koşu map()aşağıdaki sonucu verir:

>>> map(sum, list_one, list_two, list_three)
[33, 36, 39, 42, 45]

UNUTMAYIN:
Python 2'de map(), en uzun listeye göre tekrarlanır (listelerin öğelerinden geçer) ve geçerNone ve daha kısa listeler için işleve , böylece işleviniz Nonebunları aramalı ve işlemelidir, aksi takdirde hata alırsınız. Python 3'te map()en kısa liste ile bitirdikten sonra duracaktır. Ayrıca, Python 3'te map()liste değil yineleyici döndürür.


8

Python3 - harita (fonk, yinelenebilir)

Tamamen bahsedilmeyen bir şey (@BlooB da bahsetmesine rağmen) haritanın bir liste DEĞİL harita nesnesi döndürüyor olmasıdır . Başlatma ve yinelemede zaman performansı söz konusu olduğunda bu büyük bir farktır. Bu iki testi düşünün.

import time
def test1(iterable):
    a = time.clock()
    map(str, iterable)
    a = time.clock() - a

    b = time.clock()
    [ str(x) for x in iterable ]
    b = time.clock() - b

    print(a,b)


def test2(iterable):
    a = time.clock()
    [ x for x in map(str, iterable)]
    a = time.clock() - a

    b = time.clock()
    [ str(x) for x in iterable ]
    b = time.clock() - b

    print(a,b)


test1(range(2000000))  # Prints ~1.7e-5s   ~8s
test2(range(2000000))  # Prints ~9s        ~8s

Gördüğünüz gibi harita fonksiyonunun başlatılması neredeyse hiç zaman almıyor. Bununla birlikte, harita nesnesi üzerinden yineleme yapmak, yinelenebilir üzerinden yinelemekten daha uzun sürer. Bu, map () öğesine iletilen işlevin, öğeye yinelemede ulaşılana kadar her öğeye uygulanmadığı anlamına gelir. Bir liste istiyorsanız liste anlama kullanın. For döngüsünde yineleme yapmayı planlıyorsanız ve bir noktada kırılacaksanız, haritayı kullanın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.