파이썬에서 인수 목록이있는 함수 호출


150

파이썬에서 다른 함수 내부의 함수를 호출하려고하는데 올바른 구문을 찾을 수 없습니다. 내가하고 싶은 것은 다음과 같습니다.

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

이 경우 첫 번째 통화는 작동하고 두 번째 통화는 작동하지 않습니다. 내가 수정하고 싶은 것은 호출 된 함수가 아닌 래퍼 함수입니다.

답변:


268

다른 답변을 조금 확장하려면 다음을 수행하십시오.

라인에서 :

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


26
내가 자주 언급하지 않은 한 가지 사항은 전달하려는 목록이나 튜플이있는 경우 * args로 함수를 호출하는 방법입니다. 이를 위해 다음과 같이 호출해야합니다. wrapper1 (func2, * mylist)
Ali

* args in def wrapper(func, *args)method(params object[] args)C #의 내용입니다.
Jim Aho

1
참고 *args함수 정의의 마지막 인수 여야합니다.
Jim Aho

2
The * next to args means "take the rest of the parameters given and put them in a list called args".목록이 아닌 튜플에 넣습니다.
Tomasz Nocoń

20

함수를 포장하는 가장 간단한 방법

    func(*args, **kwargs)

... func ()을 호출하는 래퍼를 수동으로 작성하는 것 입니다.

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

파이썬에서 함수는 객체이므로 다른 함수의 인수로 이름을 전달하고 반환 할 수 있습니다. anyFunc () 함수에 대한 래퍼 생성기를 작성할 수도 있습니다 .

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

파이썬에서 함수의 모든 인수의 이름을 모르거나 원하지 않는 경우 인수의 튜플을 참조 할 수 있습니다. 함수 이름 :

    *args

예를 들어, 여러 개의 인수를 취하는 함수를 정의 할 수 있습니다.

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

파이썬은 함수 인수에 대한 추가 조작을 제공합니다. 함수가 키워드 인수를 받도록 허용 할 수 있습니다. 함수 본문 내에서 키워드 인수는 사전에 보관됩니다. 함수 이름 뒤의 괄호 안에이 사전은 두 개의 별표로 표시되고 그 뒤에 사전 이름이 표시됩니다.

    **kwargs

키워드 인수 사전을 인쇄하는 비슷한 예 :

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

11

가변 길이 인수에 * args 및 ** kwargs 구문을 사용할 수 있습니다.

* args 및 ** kwargs는 무엇을 의미합니까?

그리고 공식 파이썬 튜토리얼에서

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


그래서 * args와 ** kwargs를 모두 가져 와서 호출해야합니까?
SurDin

1
아니요, 둘 중 하나를 사용할 수 있지만 종종 쌍을 이룹니다. 귀하의 경우에는 * args 만 필요합니다.
JimB

좋아, 작동하지만 여전히 인수 목록을 전달할 수는 없으며 별도로 전달해야합니다. 현재 상황에서는 크게 신경 쓰지 않지만 여전히 어떻게 해야하는지 알고 싶습니다. (Wrapper (func2, [x, y, z])가 아닌 wrapper (func2, x, y, z)를 수행해야합니다.
SurDin

후자가 원하는 경우 래퍼가 func2를 호출 할 때 * args 양식을 사용하지만 'def 래퍼'에서는 사용하지 않습니다.
Alex Martelli

10

질문에 대한 리터럴 답변 (함수 또는 함수 호출이 아닌 래퍼 만 변경하여 요청한 내용을 정확하게 수행)은 단순히 행을 변경하는 것입니다.

func(args)

읽다

func(*args)

이것은 파이썬에게 주어진 목록 (이 경우 args) 을 가져 와서 그 내용을 위치 인수로 함수에 전달하도록 지시합니다.

이 트릭은 함수 호출의 양쪽에서 작동하므로 다음과 같이 정의 된 함수입니다.

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

당신이 그것을 던질 때 많은 위치 인수를 받아들이고 그것들을 모두라는 목록에 넣을 수 있습니다 args.

나는 이것이 약간 명확하게하는 데 도움이되기를 바랍니다. 이것은 **대신 dicts / keyword 인수로도 가능합니다 *.


8

압축 풀기 인수를 사용해야합니다.

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

문제에 대한 해결책을 찾을 수 없었기 때문에 이전 답변에 약간의 추가가 있었으므로 새 질문을 열 가치는 없지만 여기로 안내했습니다.

다음은 lists, zip()및 을 결합 *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(), 불평등 한 길이의 목록에 대한 안전 점검을 제공 볼 수 없습니다 우편 반복자는 파이썬에서 동일한 길이에 대한 주장 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.