함수 호출에서 스타 연산자는 무엇을 의미합니까?


631

또는 *같은 코드에서와 같이 Python 에서 연산자는 무엇을 의미 합니까?zip(*x)f(**k)

  1. 인터프리터에서 내부적으로 어떻게 처리됩니까?
  2. 성능에 전혀 영향을 미칩니 까? 빠르거나 느린가요?
  3. 언제 유용하고 유용하지 않습니까?
  4. 함수 선언이나 호출에 사용해야합니까?


4
나는 이것이 "* 함수 호출 구문"으로 표현되어야한다고 생각한다. 이대로 혼란을 얻을 것이다하지만 그들은 사업자 없습니다 입니다* 및 **구문와는 아무 상관이 연산자를.
— Ian Bicking

1
@Ian Bicking : 당신은 완전한 권리이며 인수 목록의 * 및 **는 순수한 구문 (토큰)입니다.
— P. Ortiz

2
참고 : PEP 448 : 추가 Unpacking Generalizations 특정 항목 (예 : [*a, b, *c]또는 {**d1, **d2})의 경우 튜플, 목록 및 집합 정의의 별표, dict 정의의 이중 별표 를 읽고 싶을 것입니다 . 이는 함수 호출 및 함수 정의 외부 의 사용에만 해당됩니다. . 이전 PEP 3132의 경우 시퀀스 길이를 모르는 경우 Python에서 다중 압축 해제 할당을 참조하십시오 .
— ShadowRanger

1
VTR-이것은 매개 변수에 대해 ** (이중 별표 / 별표) 및 * (별표 / 별표)가 수행하는 작업 의 중복이 아닙니다 . 그 질문은 매개 변수에 관한 것이기 때문에 대답은 함수 호출도 다루지 만. 함수 호출의 별표는 인기가 적고 상위 답변이 덜 완전하기 때문에이 질문의 중복으로 표시되어야합니다.
— wjandrea

답변:


968

단일 별 *은 시퀀스 / 컬렉션을 위치 인수로 압축 해제하므로 다음과 같이 할 수 있습니다.

def sum(a, b):
    return a + b

values = (1, 2)

s = sum(*values)

이것은 실제로 다음과 같이 실행되도록 튜플을 압축 해제합니다.

s = sum(1, 2)

이중 별표 **는 딕셔너리와 명명 된 인수 만 사용하여 동일합니다.

values = { 'a': 1, 'b': 2 }
s = sum(**values)

다음을 결합 할 수도 있습니다.

def sum(a, b, c, d):
    return a + b + c + d

values1 = (1, 2)
values2 = { 'c': 10, 'd': 15 }
s = sum(*values1, **values2)

다음과 같이 실행됩니다.

s = sum(1, 2, c=10, d=15)

또한 섹션 4.7.4- Python 문서의 인수 목록 압축 해제를 참조하십시오 .


또한 취할 함수 *x와 **y인수 를 정의 할 수 있습니다 . 이렇게하면 함수가 선언에 구체적으로 이름이 지정되지 않은 위치 및 / 또는 명명 된 인수를 얼마든지받을 수 있습니다.

예:

def sum(*values):
    s = 0
    for v in values:
        s = s + v
    return s

s = sum(1, 2, 3, 4, 5)

또는 **:

def get_a(**values):
    return values['a']

s = get_a(a=1, b=2)      # returns 1

이를 통해 선언 할 필요없이 많은 수의 선택적 매개 변수를 지정할 수 있습니다.

또한 다음을 결합 할 수 있습니다.

def sum(*values, **options):
    s = 0
    for i in values:
        s = s + i
    if "neg" in options:
        if options["neg"]:
            s = -s
    return s

s = sum(1, 2, 3, 4, 5)            # returns 15
s = sum(1, 2, 3, 4, 5, neg=True)  # returns -15
s = sum(1, 2, 3, 4, 5, neg=False) # returns 15

4
왜 이것이 필요합니까? 함수는 확장되지 않고 제공된 목록을 반복 할 수 없습니까?
— Martin Beckett

30
물론 호출해야합니다. s = sum((1, 2, 3, 4, 5))또는 s = sum([1, 2, 3, 4, 5]),이 *values옵션은 호출이 여러 인수를받는 것처럼 보이게하지만 함수 코드에 대한 컬렉션으로 압축됩니다.
— Lasse V. Karlsen

12
실제 이점은 다음과 같습니다. 가변 개수의 인수가 필요한 경우 다른 방법으로는 불가능한 함수를 작성할 수 있습니다. 예를 들어, 1 + n 개의 인수가있는 C의 printf 함수는 초보자를위한 연습용으로 작성하기가 까다 롭습니다. Python에서 초보자는 def printf (string_template, * args)를 작성하고 계속 진행할 수 있습니다.
— IceArdor 2013

1
두 개 대신 * 하나만있는 사전을 풀면 어떻게 될까요? 뭔가를하는 것 같고, 튜플이 나오는 것처럼 보이지만 그것이 무엇인지는 분명하지 않습니다. (편집 : 확인을 나는 값이 폐기, 대답은 그냥 키를 압축을 풉니 다한다는 생각)
— 벤 농부

1
마지막 예는 *와 **가 압축 풀기뿐만 아니라 압축도 수행한다는 것을 의미합니다! 이 훌륭한 페이지를 참조하십시오 codingame.com/playgrounds/500/…
— HCChen

46

한 가지 작은 요점은 운영자가 아닙니다. 연산자는 표현식에서 기존 값에서 새 값을 만드는 데 사용됩니다 (예 : 1 + 2는 3이됩니다. 여기에서 * 및 **는 함수 선언 및 호출 구문의 일부입니다.


7
Python 문서는이 문맥에서 * 연산자를 호출합니다. 동의합니다. 그것은 일종의 오해의 소지가 있습니다.
— Christophe

감사. 나는 파이썬 참조 문서에서 이것에 대한 명확한 설명을 찾고 있었지만 여전히 보이지 않습니다. 따라서 함수 호출의 규칙은 기본적으로 함수 호출 내에서 표현식의 시작 부분에있는 "*"또는 "**"가 이런 종류의 확장을 유발한다는 것입니다.
— nealmcb

21

함수 호출을 '저장'하고 싶을 때 특히 유용합니다.

예를 들어 'add'함수에 대한 단위 테스트가 있다고 가정합니다.

def add(a, b): return a + b
tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
for test, result in tests.items():
   print 'test: adding', test, '==', result, '---', add(*test) == result

추악한 add (test [0], test [1])와 같은 작업을 수동으로 수행하는 것 외에는 add를 호출하는 다른 방법이 없습니다. 또한 변수 수가 가변적이면 필요한 모든 if 문으로 코드가 매우 추악해질 수 있습니다.

이것이 유용한 또 다른 장소는 Factory 객체 (객체를 생성하는 객체)를 정의하는 것입니다. Car 객체를 만들고 반환하는 Factory 클래스가 있다고 가정합니다. myFactory.make_car ( 'red', 'bmw', '335ix')가 Car ( 'red', 'bmw', '335ix')를 생성 한 다음 반환하도록 만들 수 있습니다.

def make_car(*args):
   return Car(*args)

이것은 슈퍼 클래스의 생성자를 호출 할 때도 유용합니다.


4
나는 당신의 예를 좋아합니다. 하지만 -1 + 3 == 2.
— eksortso

5
나는 의도적으로 실패 할 무언가를 거기에 넣었습니다. :)
— Donald Miner

19

이를 확장 호출 구문이라고합니다. 로부터 문서 :

구문 * expression이 함수 호출에 나타나면 expression은 시퀀스로 평가되어야합니다. 이 시퀀스의 요소는 추가 위치 인수 인 것처럼 처리됩니다. 위치 인수 x1, ..., xN이 있고 expression이 시퀀스 y1, ..., yM으로 평가되는 경우 이는 M + N 위치 인수 x1, ..., xN, y1,을 사용하는 호출과 동일합니다. .., yM.

과:

** expression 구문이 함수 호출에 나타나면 expression은 매핑으로 평가되어야하며 그 내용은 추가 키워드 인수로 처리됩니다. 표현식과 명시 적 키워드 인수로 모두 나타나는 키워드의 경우 TypeError 예외가 발생합니다.


3
그냥 교과서 대답에 각주를 추가 - 구문 지원이 도착하기 전에, 같은 기능은 내장에 달성 된 apply()기능
— 제레미 브라운

18

함수 호출에서 하나의 별 (예 : 별도의 인수로 목록을 변 zip(*x)과 동일한 zip(x1,x2,x3)경우 x=[x1,x2,x3]예 () 및 이중 별 별도의 키워드 인수에 사전을 회전 f(**k)과 동일 f(x=my_x, y=my_y)경우 k = {'x':my_x, 'y':my_y}.

함수 정의에서는 그 반대입니다. 단일 별표는 임의 개수의 인수를 목록으로 변환하고 이중 시작은 임의 개수의 키워드 인수를 사전으로 변환합니다. 예 def foo(*x)수단 "foo는 인수의 임의의 수를 소요하고 그들이 목록 X를 통해 액세스 할 수 있습니다 (즉, 사용자 호출하는 경우 foo(1,2,3), x될 것 [1,2,3])"및 def bar(**k)수단 "바는 키워드 인자의 임의의 수를 소요하고는 사전 K를 통해 액세스 할 수 있습니다 (사용자가 호출하는 경우 즉 bar(x=42, y=23), k될 것이다 {'x': 42, 'y': 23}").


3
(매우) 늦은 주석이지만 def foo(*x)* x에서 목록이 아닌 튜플을 제공 한다고 믿습니다 .
— jeremycg
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.