Python'da aynı kaldığı fonksiyonu eşlemek için birden fazla argüman nasıl yapılır?


155

Diyelim ki aşağıdaki gibi bir fonksiyon ekledik

def add(x, y):
    return x + y

bir dizi için harita işlevini uygulamak istiyoruz

map(add, [1, 2, 3], 2)

Anlambilim dizinin her elemanına 2 eklemek istiyorum. Ancak mapişlev, üçüncü argümanda da bir liste gerektirir.

Not: Basitlik için örnek ekliyorum. Orijinal fonksiyonum çok daha karmaşık. Ve tabii ki yadd-in fonksiyonunun varsayılan değerini ayarlama seçeneği her çağrı için değiştirileceğinden söz konusu değildir.


20
Bu Lisp ile tamamen aynıdır: map(add,[1,2,3],[2]*3) genel mapolarak ilk argümanı gibi bir işlevi alır ve bu işlev K argümanını alırsa , K iterable ile takip etmek zorundasınız:addTriple(a,b,c) -> map(addTriple,[...],[...],[...])
watashiSHUN

Yanıtlar:


188

Seçeneklerden biri bir liste kavramasıdır:

[add(x, 2) for x in [1, 2, 3]]

Daha fazla seçenek:

a = [1, 2, 3]

import functools
map(functools.partial(add, y=2), a)

import itertools
map(add, a, itertools.repeat(2, len(a)))

1
Evet, ama harita fonksiyonuna kıyasla ne kadar hızlı?
Shan

@Shan: Çok benzer, özellikle add()önemsiz olmayan bir
işlevse

2
@Shan: Bu durumda NumPy'ye bir göz atın. Bu gerçekten sizin için bir sorunsa, liste kavrayışları arasındaki hız farkı ve map()her iki şekilde de yardımcı olmaz.
Sven Marnach

3
@Shan: Daha önce söylediğim gibi NumPy'ye bir göz atın. Vektörleştirilebilmeleri koşuluyla döngülerin hızlanmasına yardımcı olabilir.
Sven Marnach

1
@abarnert: OP'nin Python 2 veya 3'ü kullanıp kullanmadığı belli değil. Örneğin Python 2'de çalıştığından emin olmak için parametreyi dahil ettim. (Not bu map()davranacağını gibi zip_longest()o gibi davranır ise, Python 2'de zip()Python 3'te)
Sven Marnach

60

Belgeler bunun ana kullanım alanı olduğunu açıkça belirtmektedir itertools.repeat:

Nesneyi tekrar tekrar döndüren bir yineleyici yapın. Times argümanı belirtilmedikçe süresiz olarak çalışır. map()Aranan işleve değişmez parametreler için argüman olarak kullanılır . Ayrıca zip()bir kayıt kaydının değişmez bir parçasını oluşturmak için ile kullanılır .

Ve argüman len([1,2,3])olarak geçmek için bir sebep yok times; mapilk yinelenebilir tüketilir tükenmez, bu yüzden sonsuz bir yinelenebilir mükemmel para cezası:

>>> from operator import add
>>> from itertools import repeat
>>> list(map(add, [1,2,3], repeat(4)))
[5, 6, 7]

Aslında bu, repeatdokümanlardaki örneğe eşdeğerdir :

>>> list(map(pow, range(10), repeat(2)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Bu, Python-iterator açısından da mükemmel bir şekilde okunabilen hoş bir tembel-fonksiyonel-dil-y çözümü sağlar.


2
+1 Bu kabul edilen cevap olmalıdır. Tabii ki, bazı sabit ve diğer listeler veya jeneratörler ile herhangi bir sayıda parametreye uzanır. Örneğin: def f(x,y,z): \\ return '.'.join([x,y,z])ve sonra: list(map(f, list('abc'), repeat('foo'), list('defgh')))döner ['a.foo.d', 'b.foo.e', 'c.foo.f'].
Pierre D

5
Python 2'de, uzunluk argümanını sağlamak gerekir repeat(), çünkü Python'un bu sürümünde en uzun yineleyici map()tükenene kadar çalışır ve tüm eksik değerleri doldurur . Parametreyi geçmek için "sebep yok" demek yanlıştır. None
Sven Marnach

@SvenMarnach'ın yorumu küçük değildir: Python 3 ve Python 2'nin davranışı büyük ölçüde değişir!
Agustín

36

Bir liste kavrayışı kullanın.

[x + 2 for x in [1, 2, 3]]

Eğer varsa gerçekten , gerçekten , gerçekten kullanmak istiyorum map, o ilk argüman olarak bir anonim işlev vermek:

map(lambda x: x + 2, [1,2,3])

16

Harita birden fazla argüman içerebilir, standart yol

map(add, a, b)

Sorunuzda, bu olmalı

map(add, a, [2]*len(a))

Emin onun sorusunun ne anlama geldiğini ama ben 2 değeri kabul düşünüyorum ve bu 2 sabit değildir ve arg1 gibi kullanıcı geliyor olmalıdır. peki bu durumda nasıl haritaya add (x, y) diyelim?
Bimlesh Sharma

15

Doğru cevap sandığınızdan daha basit. Basitçe yapın:

map(add, [(x, 2) for x in [1,2,3]])

Ve bir tuple almak için add uygulamasını değiştirin yani

def add(t):
   x, y = t
   return x+y

Bu, her iki ekleme parametresinin de dinamik olduğu karmaşık kullanım durumlarını işleyebilir.


14

Bazen kapanışları kullanarak benzer durumları ( pandas.apply yöntemini kullanmak gibi ) çözdüm

Bunları kullanmak için, işleviniz için dinamik olarak tanımlayan ve döndüren bir işlev tanımlar ve parametrelerden birini etkili bir şekilde sabit hale getirirsiniz.

Bunun gibi bir şey:

def add(x, y):
   return x + y

def add_constant(y):
    def f(x):
        return add(x, y)
    return f

Ardından, verilen herhangi bir değere add_constant(y)eklemek yiçin kullanılabilecek bir işlev döndürür :

>>> add_constant(2)(3)
5

Bu, parametrelerin birer birer verildiği herhangi bir durumda kullanmanıza izin verir:

>>> map(add_constant(2), [1,2,3])
[3, 4, 5]

Düzenle

Kapatma işlevini başka bir yere yazmak istemiyorsanız, lambda işlevini kullanarak her zaman anında oluşturma olanağınız vardır:

>>> map(lambda x: add(x, 2), [1, 2, 3])
[3, 4, 5]

13

Eğer mevcutsa, numpy kullanmayı düşünürdüm. Bu tür işlemler için çok hızlı:

>>> import numpy
>>> numpy.array([1,2,3]) + 2
array([3, 4, 5])

Bu, gerçek uygulamanızın matematiksel işlemler yaptığını varsayar (bu vektörleştirilebilir).


10

Harita işlevini gerçekten kullanmanız gerekiyorsa (buradaki sınıf ödevim gibi ...), 1 argümanlı bir sarmalayıcı işlevini kullanabilirsiniz, gerisini vücudundaki orijinal olana geçirin; yani:

extraArguments = value
def myFunc(arg):
    # call the target function
    return Func(arg, extraArguments)


map(myFunc, itterable)

Kirli ve çirkin, hala hile yapıyor


1
Bir kapanış, bence bu artı bir şey ekliyor. Kısmi bir işleve benzer şekilde, kabul edilen cevapta olduğu gibi.
Aaron Hall

1
myFuncihtiyacı varreturn Func(arg, extraArguments)
PM 2Ring

Ben düzeltilmiş @ PM2Ring, bu doğru; kodu güncelledi.
Todor Minakov

Func nerede tanımlanır? Ben Func için bir ad hatası alıyorum çünkü
Nikhil Mishra

Funcorijinal fonksiyonunuzun adıdır - OP sıkı addiçin örneğin
Todor Minakov

6

Starmap'ın ihtiyacınız olan şey olduğuna inanıyorum:

from itertools import starmap


def test(x, y, z):
    return x + y + z

list(starmap(test, [(1, 2, 3), (4, 5, 6)]))

Örneğinizdeki yazım hatası: list (starmap (test, [(1, 2, 3), (4, 5, 6)])))
Teebu

Oh evet. Teşekkürler :)
Shqi.Yang

1

Bir mapişleve birden çok argüman iletmek için .

def q(x,y):
    return x*y

print map (q,range(0,10),range(10,20))

Burada q , map () işlevinin çağırdığı çoklu argümanlı işlevdir . Her iki aralığın uzunluğunun,

len (range(a,a')) and len (range(b,b')) are equal.


1

Lamda'yı harita ile birlikte ekleyebilirsiniz:

list(map(lambda a: a+2, [1, 2, 3]))

1
def func(a, b, c, d):
 return a + b * c % d
map(lambda x: func(*x), [[1,2,3,4], [5,6,7,8]])

Fonksiyon çağrısını lambda ile sararak ve yıldız paketini kullanarak, rastgele sayıda argümanla harita yapabilirsiniz.


lambda çok yavaş, yerine functools kullanın
Wang

0

Başka bir seçenek:

results = []
for x in [1,2,3]:
    z = add(x,2)
    ...
    results += [f(z,x,y)]

Bu biçim, birden çok işlevi çağırırken çok kullanışlıdır.

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.