web-dev-qa-db-ja.com

pythonの引数リストで関数を呼び出します

私はPythonで別の関数内の関数を呼び出そうとしていますが、正しい構文が見つかりません。私がやりたいのはこのようなものです:

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

この場合、最初の呼び出しは機能し、2番目の呼び出しは機能しません。変更したいのはラッパー関数であり、呼び出された関数ではありません。

137
SurDin

他の答えを少し拡大するには:

行内:

def wrapper(func, *args):

argsの横にある*は、「指定された残りのパラメーターを取得し、argsという名前のリストに入れる」ことを意味します。

行内:

    func(*args)

ここでargsの横にある*は、「argsという名前のこのリストを残りのパラメーターに「アンラップ」することを意味します。

したがって、次のことができます。

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

wrapper2では、リストが明示的に渡されますが、両方のラッパーargsにはリスト[1,2,3]が含まれます。

251
itsadok

関数をラップする最も簡単な方法

    func(*args, **kwargs)

...は、内部でfunc()を呼び出すラッパーを手動で記述することです。

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

Pythonでは、関数はオブジェクトなので、その名前を別の関数の引数として渡し、それを返すことができます。任意の関数のラッパージェネレーターを書くこともできますanyFunc()

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

関数のすべての引数を知らない場合や名前を付けたくない場合は、Pythonで、引数のタプルを参照できます。関数名の後の括弧内のアスタリスク:

    *args

たとえば、任意の数の引数を取る関数を定義できます。

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

Pythonでは、関数の引数をさらに操作できます。関数がキーワード引数を取ることを許可できます。関数の本体内で、キーワード引数は辞書に保持されます。関数名の後の括弧内では、この辞書は2つのアスタリスクとそれに続く辞書名で示されます。

    **kwargs

キーワード引数辞書を出力する同様の例:

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

可変長引数には* argsおよび** kwargs構文を使用できます。

* argsと** kwargsはどういう意味ですか?

公式のpythonチュートリアルから

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

10
JimB

あなたの質問に対する文字通りの答え(あなたが尋ねたとおりに正確に行うには、関数または関数呼び出しではなくラッパーのみを変更する)は、単に行を変更することです

func(args)

読む

func(*args)

これにより、Pythonに指定されたリスト(この場合はargs)を取得し、その内容を位置引数として関数に渡すように指示します。

このトリックは、関数呼び出しの両側で機能するため、関数は次のように定義されます。

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

あなたはそれを投げるのと同じくらい多くの位置引数を受け入れ、それらをすべてargsと呼ばれるリストに入れることができるでしょう。

これが少し物事を明確にするのに役立つことを願っています。これは、**の代わりに*を使用して、dicts/keyword引数でも同様に可能です。

9
Alan Rowarth

引数のアンパックを使用する必要があります。

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)
8
Joril

問題の解決策を見つけることができなかったため、以前の回答に少し追加されました。これは新しい質問を開く価値はありませんが、ここで私を導きました。

listsZip()、および*argsを組み合わせた小さなコードスニペットは、未知の量の引数を持つ未知の量の関数を処理できるラッパーを提供します。

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()は、長さが等しくないリストの安全性チェックを提供しないことに注意してください。 Pythonで等しい長さをアサートするZipイテレーター を参照してください。

0
P. Siehr