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


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.