Python'da bağımsız değişken listesi olan bir işlevi çağırma


150

Bir işlevi python içinde başka bir işlev içinde çağırmaya çalışıyorum, ancak doğru sözdizimi bulamıyorum. Ne yapmak istiyorum böyle bir şeydir:

def wrapper(func, args):
    func(args)

def func1(x):
    print(x)

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

wrapper(func1, [x])
wrapper(func2, [x, y, z])

Bu durumda ilk çağrı çalışır, ikincisi çalışmaz. Ne değiştirmek istiyorum sarma işlevi, çağrılan işlevleri değil.

Yanıtlar:


268

Diğer cevapları biraz genişletmek için:

Çizgide:

def wrapper(func, *args):

args" Yanındaki " ifadesi, verilen parametrelerin geri kalanını alın ve şu adlı bir listeye yerleştirin:args " .

Çizgide:

    func(*args)

Buradaki * yanındaki args"args adlı listeyi al ve parametrelerin geri kalanına" paketten çıkar ".

Böylece aşağıdakileri yapabilirsiniz:

def wrapper1(func, *args): # with star
    func(*args)

def wrapper2(func, args): # without star
    func(*args)

def func2(x, y, z):
    print x+y+z

wrapper1(func2, 1, 2, 3)
wrapper2(func2, [1, 2, 3])

İçinde wrapper2, liste açıkça geçirilir, ancak her iki paketleyicide argsde liste bulunur [1,2,3].


26
Çok sık bahsetmediğim bir şey, geçmek istediğiniz bir liste veya demet varsa, * args ile bir işlevi nasıl arayacağınızdır. Bunun için böyle çağırmanız gerekir: wrapper1 (func2, * mylist)
Ali

* Args, C # ' def wrapper(func, *args)da olan şeydir method(params object[] args).
Jim Aho

1
Bunun *argsişlev tanımındaki son bağımsız değişken olması gerektiğini unutmayın .
Jim Aho

2
The * next to args means "take the rest of the parameters given and put them in a list called args".Onları bir listeye değil, bir demet haline getirir.
Tomasz Nocoń

20

Bir işlevi sarmanın en kolay yolu

    func(*args, **kwargs)

... kendi içinde func () diyebilecek bir sarıcı yazmaktır :

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after

Python işlevinde bir nesnedir, bu yüzden adını başka bir işlevin bağımsız değişkeni olarak iletebilir ve geri verebilirsiniz. Herhangi bir işlev için anyFunc () için bir sarıcı oluşturucu da yazabilirsiniz :

    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper

Ayrıca, bir işlevin tüm argümanlarını bilmediğinizde veya adlandırmak istemediğinizde Python'da, adından sonra gelen parantezlerde yıldız işareti bulunan bir dizi argümana başvurabileceğinizi lütfen unutmayın. işlev adı:

    *args

Örneğin, herhangi bir sayıda bağımsız değişken alacak bir işlev tanımlayabilirsiniz:

    def testFunc(*args):
        print args    # prints the tuple of arguments

Python, işlev argümanlarında daha fazla manipülasyon sağlar. Bir işlevin anahtar kelime bağımsız değişkenleri almasına izin verebilirsiniz. İşlev gövdesi içinde, anahtar kelime bağımsız değişkenleri sözlükte tutulur. İşlev adından sonraki parantezlerde bu sözlük iki yıldız ve ardından sözlüğün adı ile gösterilir:

    **kwargs

Anahtar kelime bağımsız değişkenleri sözlüğünü yazan benzer bir örnek:

    def testFunc(**kwargs):
        print kwargs    # prints the dictionary of keyword arguments

11

Değişken uzunluklu bağımsız değişkenler için * args ve ** kwargs sözdizimini kullanabilirsiniz.

* Args ve ** kwargs ne anlama geliyor?

Ve resmi python öğreticisinden

http://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions


Bu yüzden hem * args hem de ** kwarg'ları alıp onlarla çağırmam gerekiyor mu?
SurDin

1
Hayır, herhangi birini / veya kullanabilirsiniz, ancak genellikle birlikte eşleştirilirler. Sizin durumunuzda, sadece * argümanlara ihtiyacınız var.
JimB

Tamam, işe yarıyor, ama yine de bir tartışma listesi geçirmeme izin vermiyor ve onları ayrı ayrı geçirmem gerekiyor. Şu anki durumumda beni fazla rahatsız etmiyor, ama bunu nasıl yapacağımı bilmek yine de iyi olurdu. (Sarıcı (func2, x, y, z) yapmam ve sarıcı (func2, [x, y, z])
yapmam gerekiyor

İkincisi istediğiniz şeyse, sarmalayıcı func2'yi çağırdığında * args formunu kullanın, ancak 'def sarmalayıcısında' kullanmayın.
Alex Martelli

10

Sorunuzun gerçek cevabı (tam olarak sorduğunuz şeyi yapmak, işlevleri veya işlev çağrılarını değil, yalnızca sarmalayıcıyı değiştirmek) basitçe satırı değiştirmek

func(args)

okumak

func(*args)

Bu Python'a verilen listeyi almasını söyler (bu durumda, args ) ve içeriğini işleve bağımsız değişkenler olarak aktarmasını .

Bu hile işlev çağrısının her iki "tarafında" çalışır, bu nedenle şöyle bir işlev tanımlanır:

def func2(*args):
    return sum(args)

attığınız kadar çok sayıda konumsal argümanı kabul edebilir ve hepsini adlı bir listeye yerleştirebilirsiniz args.

Umarım bu biraz şeyleri açıklığa kavuşturmaya yardımcı olur. **Bunun yerine dicts / keyword argümanlarıyla da mümkün olduğunu unutmayın *.


8

Paketi açarken argümanlar kullanmanız gerekir.

def wrapper(func, *args):
    func(*args)

def func1(x):
    print(x)

def func2(x, y, z):
    print x+y+z

wrapper(func1, 1)
wrapper(func2, 1, 2, 3)

0

Önceki cevaplara küçük bir katkı, çünkü bir soruna çözüm bulamadım, bu yeni bir soru açmaya değmez, ama beni buraya getirdi.

İşte küçük bir kod parçacığı, birleştirir olduğunu lists, zip()ve *argstartışmaların bilinmeyen bir miktarı ile fonksiyonların bilinmeyen bir miktarı ile başa çıkabilirim bir ambalaj sağlamaktır.

def f1(var1, var2, var3):
    print(var1+var2+var3)

def f2(var1, var2):
    print(var1*var2)

def f3():
    print('f3, empty')

def wrapper(a,b, func_list, arg_list):
    print(a)
    for f,var in zip(func_list,arg_list):
        f(*var)
    print(b)

f_list = [f1, f2, f3]
a_list = [[1,2,3], [4,5], []]

wrapper('begin', 'end', f_list, a_list)

zip()Eşit olmayan uzunluktaki listeler için bir güvenlik kontrolü sağlamadığını unutmayın, python'da eşit uzunluk için iddia eden zip yineleyicilerine bakı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.