다음 메서드 정의에서 *
및 **
는 param2
무엇을 합니까?
def foo(param1, *param2): def bar(param1, **param2):
질문자 :Todd
다음 메서드 정의에서 *
및 **
는 param2
무엇을 합니까?
def foo(param1, *param2): def bar(param1, **param2):
*args
및 **kwargs
는 Python 문서의 함수 정의 에 대한 추가 섹션에 설명된 대로 함수에 임의의 수의 인수를 허용하는 일반적인 관용구입니다.
*args
는 모든 함수 매개변수 를 튜플로 제공합니다 .
def foo(*args): for a in args: print(a) foo(1) # 1 foo(1,2,3) # 1 # 2 # 3
**kwargs
는 사전으로 형식 매개변수에 해당하는 것을 제외한 모든 키워드 인수를 제공합니다.
def bar(**kwargs): for a in kwargs: print(a, kwargs[a]) bar(name='one', age=27) # name one # age 27
두 관용구를 일반 인수와 혼합하여 고정 인수와 일부 가변 인수를 허용할 수 있습니다.
def foo(kind, *args, **kwargs): pass
이것을 반대로 사용할 수도 있습니다:
def foo(a, b, c): print(a, b, c) obj = {'b':10, 'c':'lee'} foo(100,**obj) # 100 10 lee
*l
관용구의 또 다른 사용법은 함수를 호출할 때 인수 목록의 압축을 푸는 것입니다.
def foo(bar, lee): print(bar, lee) l = [1,2] foo(*l) # 1 2
Python 3에서는 할당의 왼쪽에 *l
을 사용할 수 있지만( Extended Iterable Unpacking ), 이 컨텍스트에서는 튜플 대신 목록을 제공합니다.
first, *rest = [1,2,3,4] first, *l, last = [1,2,3,4]
또한 Python 3은 새로운 의미 체계를 추가합니다( PEP 3102 참조).
def func(arg1, arg2, arg3, *, kwarg1, kwarg2): pass
이러한 함수는 3개의 위치 인수만 허용하며 *
이후의 모든 항목은 키워드 인수로만 전달할 수 있습니다.
dict
그러나 Python 3.6에서 키워드 인수는 삽입 순서를 기억하도록 보장됩니다.**kwargs
의 요소 순서는 이제 키워드 인수가 함수에 전달된 순서와 일치합니다." - Python 3.6의 새로운 기능함수를 호출할 때도 *
및 **
사용할 수 있다는 점도 주목할 가치가 있습니다. 이것은 목록/튜플 또는 사전을 사용하여 여러 인수를 함수에 직접 전달할 수 있는 바로 가기입니다. 예를 들어 다음 기능이 있는 경우:
def foo(x,y,z): print("x=" + str(x)) print("y=" + str(y)) print("z=" + str(z))
다음과 같은 작업을 수행할 수 있습니다.
>>> mylist = [1,2,3] >>> foo(*mylist) x=1 y=2 z=3 >>> mydict = {'x':1,'y':2,'z':3} >>> foo(**mydict) x=1 y=2 z=3 >>> mytuple = (1, 2, 3) >>> foo(*mytuple) x=1 y=2 z=3
참고: mydict
foo
의 매개변수와 정확히 같은 이름을 지정해야 합니다. 그렇지 않으면 TypeError
.
>>> mydict = {'x':1,'y':2,'z':3,'badnews':9} >>> foo(**mydict) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: foo() got an unexpected keyword argument 'badnews'
단일 *는 추가 위치 인수가 여러 개 있을 수 있음을 의미합니다. foo()
foo(1,2,3,4,5)
처럼 호출할 수 있습니다. foo()의 본문에서 param2는 2-5를 포함하는 시퀀스입니다.
이중 **은 추가 명명된 매개변수가 얼마든지 있을 수 있음을 의미합니다. bar()
bar(1, a=2, b=3)
처럼 호출할 수 있습니다. bar()의 본문에서 param2는 {'a':2, 'b':3 }을 포함하는 사전입니다.
다음 코드로:
def foo(param1, *param2): print(param1) print(param2) def bar(param1, **param2): print(param1) print(param2) foo(1,2,3,4,5) bar(1,a=2,b=3)
출력은
1 (2, 3, 4, 5) 1 {'a': 2, 'b': 3}
**
(이중 별표) 및*
(별표)는 매개변수에 대해 무엇을 합니까?
이를 통해 사용자는 위치( *
) 및 키워드( **
)와 같은 인수를 허용하도록 정의하고 사용자가 인수를 전달할 수 있습니다.
*args
튜플 이름에 할당한다 선택 위치 인수 (파라미터)의 임의의 수의 허용 args
.
**kwargs
사전인가라는 이름에있을 것입니다 선택적 키워드 인수 (매개 변수), 임의의 수의 수 있습니다 kwargs
.
적절한 이름을 선택할 수 있고 선택해야 하지만, 인수가 비특정 의미론을 사용하려는 경우 args
및 kwargs
가 표준 이름입니다.
*args
및 **kwargs
를 사용하여 각각 목록(또는 모든 반복 가능) 및 dict(또는 모든 매핑)에서 매개변수를 전달할 수 있습니다.
매개변수를 수신하는 함수는 매개변수가 확장되고 있음을 알 필요가 없습니다.
예를 들어 Python 2의 xrange는 *args
명시적으로 기대하지 않지만 인수로 3개의 정수를 취하기 때문에:
>>> x = xrange(3) # create our *args - an iterable of 3 integers >>> xrange(*x) # expand here xrange(0, 2, 2)
str.format
에서 dict 확장을 사용할 수 있습니다.
>>> foo = 'FOO' >>> bar = 'BAR' >>> 'this is foo, {foo} and bar, {bar}'.format(**locals()) 'this is foo, FOO and bar, BAR'
*args
뒤에 키워드 전용 인수를 가질 수 있습니다. 예를 들어, 여기에서 kwarg2
는 위치가 아닌 키워드 인수로 제공되어야 합니다.
def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs): return arg, kwarg, args, kwarg2, kwargs
용법:
>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz') (1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})
또한 *
는 위치 인수를 무제한으로 허용하지 않고 키워드 전용 인수가 뒤따른다는 것을 나타내기 위해 단독으로 사용할 수 있습니다.
def foo(arg, kwarg=None, *, kwarg2=None, **kwargs): return arg, kwarg, kwarg2, kwargs
여기서 kwarg2
다시 명시적으로 명명된 키워드 인수여야 합니다.
>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar') (1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})
*args*
가 없기 때문에 더 이상 무제한 위치 인수를 허용할 수 없습니다.
>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: foo() takes from 1 to 2 positional arguments but 5 positional arguments (and 1 keyword-only argument) were given
다시 말하지만, 여기에서 kwarg
는 위치가 아닌 이름으로 지정해야 합니다.
def bar(*, kwarg=None): return kwarg
이 예에서 kwarg
위치적으로 전달하려고 하면 오류가 발생합니다.
>>> bar('kwarg') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: bar() takes 0 positional arguments but 1 was given
kwarg
매개변수를 키워드 인수로 명시적으로 전달해야 합니다.
>>> bar(kwarg='kwarg') 'kwarg'
*args
(일반적으로 "star-args"라고 함) 및 **kwargs
(별은 "kwargs"라고 함축할 수 있지만 "이중 별 kwargs"로 명시적임)는 *
및 **
표기법을 사용하는 Python의 일반적인 관용구입니다. . 이러한 특정 변수 이름은 필요하지 않지만(예: *foos
및 **bars
사용할 수 있음), 규칙에서 벗어나면 동료 Python 코더를 화나게 할 수 있습니다.
우리는 일반적으로 함수가 무엇을 받을지 또는 얼마나 많은 인수를 전달할지 모를 때 사용하며 때로는 모든 변수의 이름을 별도로 지정하는 것이 매우 지저분하고 중복될 때도 있습니다(그러나 이것은 일반적으로 명시적 묵시적 인 것보다 낫습니다).
실시예 1
다음 기능은 사용 방법을 설명하고 동작을 보여줍니다. 명명된 b
인수는 다음 이전의 두 번째 위치 인수에 의해 사용됩니다.
def foo(a, b=10, *args, **kwargs): ''' this function takes required argument a, not required keyword argument b and any number of unknown positional arguments and keyword arguments after ''' print('a is a required argument, and its value is {0}'.format(a)) print('b not required, its default value is 10, actual value: {0}'.format(b)) # we can inspect the unknown arguments we were passed: # - args: print('args is of type {0} and length {1}'.format(type(args), len(args))) for arg in args: print('unknown arg: {0}'.format(arg)) # - kwargs: print('kwargs is of type {0} and length {1}'.format(type(kwargs), len(kwargs))) for kw, arg in kwargs.items(): print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg)) # But we don't have to know anything about them # to pass them to other functions. print('Args or kwargs can be passed without knowing what they are.') # max can take two or more positional args: max(a, b, c...) print('eg max(a, b, *args) \n{0}'.format( max(a, b, *args))) kweg = 'dict({0})'.format( # named args same as unknown kwargs ', '.join('{k}={v}'.format(k=k, v=v) for k, v in sorted(kwargs.items()))) print('eg dict(**kwargs) (same as {kweg}) returns: \n{0}'.format( dict(**kwargs), kweg=kweg))
help(foo)
를 사용하여 함수 서명에 대한 온라인 도움말을 확인할 수 있습니다.
foo(a, b=10, *args, **kwargs)
foo(1, 2, 3, 4, e=5, f=6, g=7)
이 함수를 호출합시다.
다음을 인쇄합니다.
a is a required argument, and its value is 1 b not required, its default value is 10, actual value: 2 args is of type <type 'tuple'> and length 2 unknown arg: 3 unknown arg: 4 kwargs is of type <type 'dict'> and length 3 unknown kwarg - kw: e, arg: 5 unknown kwarg - kw: g, arg: 7 unknown kwarg - kw: f, arg: 6 Args or kwargs can be passed without knowing what they are. eg max(a, b, *args) 4 eg dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns: {'e': 5, 'g': 7, 'f': 6}
실시예 2
a
다른 함수를 사용하여 호출할 수도 있습니다.
def bar(a): b, c, d, e, f = 2, 3, 4, 5, 6 # dumping every local variable into foo as a keyword argument # by expanding the locals dict: foo(**locals())
bar(100)
인쇄:
a is a required argument, and its value is 100 b not required, its default value is 10, actual value: 2 args is of type <type 'tuple'> and length 0 kwargs is of type <type 'dict'> and length 4 unknown kwarg - kw: c, arg: 3 unknown kwarg - kw: e, arg: 5 unknown kwarg - kw: d, arg: 4 unknown kwarg - kw: f, arg: 6 Args or kwargs can be passed without knowing what they are. eg max(a, b, *args) 100 eg dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns: {'c': 3, 'e': 5, 'd': 4, 'f': 6}
예제 3: 데코레이터에서의 실제 사용
좋아, 어쩌면 우리는 아직 유틸리티를 보지 못하고 있을지도 모른다. 따라서 차별화 코드 전후에 중복 코드가 있는 여러 기능이 있다고 상상해 보십시오. 다음 명명된 함수는 설명을 위한 의사 코드일 뿐입니다.
def foo(a, b, c, d=0, e=100): # imagine this is much more code than a simple function call preprocess() differentiating_process_foo(a,b,c,d,e) # imagine this is much more code than a simple function call postprocess() def bar(a, b, c=None, d=0, e=100, f=None): preprocess() differentiating_process_bar(a,b,c,d,e,f) postprocess() def baz(a, b, c, d, e, f): ... and so on
이것을 다르게 처리할 수도 있지만 데코레이터로 중복성을 확실히 추출할 수 있으므로 아래 예제는 *args
및 **kwargs
가 어떻게 매우 유용할 수 있는지 보여줍니다.
def decorator(function): '''function to wrap other functions with a pre- and postprocess''' @functools.wraps(function) # applies module, name, and docstring to wrapper def wrapper(*args, **kwargs): # again, imagine this is complicated, but we only write it once! preprocess() function(*args, **kwargs) postprocess() return wrapper
이제 모든 래핑된 함수는 중복성을 제거했기 때문에 훨씬 더 간결하게 작성할 수 있습니다.
@decorator def foo(a, b, c, d=0, e=100): differentiating_process_foo(a,b,c,d,e) @decorator def bar(a, b, c=None, d=0, e=100, f=None): differentiating_process_bar(a,b,c,d,e,f) @decorator def baz(a, b, c=None, d=0, e=100, f=None, g=None): differentiating_process_baz(a,b,c,d,e,f, g) @decorator def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None): differentiating_process_quux(a,b,c,d,e,f,g,h)
*args
및 **kwargs
허용하는 코드를 제외함으로써 코드 줄을 줄이고 가독성과 유지 관리성을 개선하며 프로그램의 논리에 대한 유일한 표준 위치를 갖게 됩니다. 이 구조의 일부를 변경해야 하는 경우 각 변경을 수행할 수 있는 한 곳이 있습니다.
먼저 위치 인수와 키워드 인수가 무엇인지 이해합시다. 다음은 위치 인수를 사용한 함수 정의의 예입니다.
def test(a,b,c): print(a) print(b) print(c) test(1,2,3) #output: 1 2 3
따라서 이것은 위치 인수가 있는 함수 정의입니다. 키워드/명명된 인수로 호출할 수도 있습니다.
def test(a,b,c): print(a) print(b) print(c) test(a=1,b=2,c=3) #output: 1 2 3
이제 키워드 인수를 사용 하여 함수 정의의 예를 연구해 보겠습니다.
def test(a=0,b=0,c=0): print(a) print(b) print(c) print('-------------------------') test(a=1,b=2,c=3) #output : 1 2 3 -------------------------
위치 인수를 사용하여 이 함수를 호출할 수도 있습니다.
def test(a=0,b=0,c=0): print(a) print(b) print(c) print('-------------------------') test(1,2,3) # output : 1 2 3 ---------------------------------
그래서 우리는 이제 키워드 인수뿐만 아니라 위치 인수가 있는 함수 정의를 알고 있습니다.
이제 '*' 연산자와 '**' 연산자에 대해 알아보겠습니다.
이 연산자는 2가지 영역에서 사용할 수 있습니다.
a) 함수 호출
b) 기능 정의
함수 호출 에서 '*' 연산자와 '**' 연산자 사용.
예제를 직접 본 다음 논의해 보겠습니다.
def sum(a,b): #receive args from function calls as sum(1,2) or sum(a=1,b=2) print(a+b) my_tuple = (1,2) my_list = [1,2] my_dict = {'a':1,'b':2} # Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator sum(*my_tuple) # becomes same as sum(1,2) after unpacking my_tuple with '*' sum(*my_list) # becomes same as sum(1,2) after unpacking my_list with '*' sum(**my_dict) # becomes same as sum(a=1,b=2) after unpacking by '**' # output is 3 in all three calls to sum function.
그러니 기억해
함수 호출 에서 '*' 또는 '**' 연산자를 사용하는 경우 -
'*' 연산자는 목록 또는 튜플과 같은 데이터 구조를 함수 정의에 필요한 인수로 압축을 풉니다.
'**' 연산자는 사전을 함수 정의에 필요한 인수로 압축을 풉니다.
이제 함수 정의 에서 '*' 연산자 사용을 연구해 보겠습니다. 예시:
def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4)) sum = 0 for a in args: sum+=a print(sum) sum(1,2,3,4) #positional args sent to function sum #output: 10
함수 정의 에서 '*' 연산자는 수신된 인수를 튜플로 압축합니다.
이제 함수 정의에 사용된 '**'의 예를 살펴보겠습니다.
def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4}) sum=0 for k,v in args.items(): sum+=v print(sum) sum(a=1,b=2,c=3,d=4) #positional args sent to function sum
함수 정의 에서 '**' 연산자는 수신된 인수를 사전에 압축합니다.
따라서 다음을 기억하십시오.
함수 호출 에서 '*'는 튜플 또는 목록의 데이터 구조를 함수 정의에서 수신할 위치 또는 키워드 인수로 압축을 풉니다.
함수 호출 에서 '**'는 사전의 데이터 구조를 함수 정의에서 수신할 위치 또는 키워드 인수로 압축을 풉니다.
함수 정의 에서 '*' 는 위치 인수를 튜플로 압축합니다.
함수 정의 에서 '**' 는 키워드 인수를 사전으로 압축합니다.
이 테이블은 함수 생성 및 함수 호출 *
및 **
를 사용하는 데 유용합니다.
In function construction In function call ======================================================================= | def f(*args): | def f(a, b): *args | for arg in args: | return a + b | print(arg) | args = (1, 2) | f(1, 2) | f(*args) ----------|--------------------------------|--------------------------- | def f(a, b): | def f(a, b): **kwargs | return a + b | return a + b | def g(**kwargs): | kwargs = dict(a=1, b=2) | return f(**kwargs) | f(**kwargs) | g(a=1, b=2) | -----------------------------------------------------------------------
이것은 실제로 Lorin Hochstein의 답변 을 요약하는 역할을 하지만 도움이 된다고 생각합니다.
관련: 스타/스플랫 연산자의 사용이 Python 3에서 확장되었습니다.
*
및 **
는 함수 인수 목록에서 특별한 용도로 사용됩니다. *
는 인수가 목록 **
는 인수가 사전임을 의미합니다. 이를 통해 함수는 임의의 수의 인수를 사용할 수 있습니다.
*
의 목적은 목록으로 제공된 임의의 수의 인수를 사용할 수 있는 함수를 정의하는 기능을 제공하는 것입니다(예: f(*myList)
).**
의 목적은 f(**{'x' : 1, 'y' : 2})
)을 제공하여 함수의 인수를 제공하는 기능을 제공하는 것입니다. x
, y
를 사용하고 더 많은 인수를 myArgs
로 허용하고 더 많은 인수를 myKW 로 허용할 수 있는 함수를 정의하여 이를 보여 myKW
. myArgDict
사용하여 y
를 입력하는 방법을 보여줍니다.
def f(x, y, *myArgs, **myKW): print("# x = {}".format(x)) print("# y = {}".format(y)) print("# myArgs = {}".format(myArgs)) print("# myKW = {}".format(myKW)) print("# ----------------------------------------------------------------------") # Define a list for demonstration purposes myList = ["Left", "Right", "Up", "Down"] # Define a dictionary for demonstration purposes myDict = {"Wubba": "lubba", "Dub": "dub"} # Define a dictionary to feed y myArgDict = {'y': "Why?", 'y0': "Why not?", "q": "Here is a cue!"} # The 1st elem of myList feeds y f("myEx", *myList, **myDict) # x = myEx # y = Left # myArgs = ('Right', 'Up', 'Down') # myKW = {'Wubba': 'lubba', 'Dub': 'dub'} # ---------------------------------------------------------------------- # y is matched and fed first # The rest of myArgDict becomes additional arguments feeding myKW f("myEx", **myArgDict) # x = myEx # y = Why? # myArgs = () # myKW = {'y0': 'Why not?', 'q': 'Here is a cue!'} # ---------------------------------------------------------------------- # The rest of myArgDict becomes additional arguments feeding myArgs f("myEx", *myArgDict) # x = myEx # y = y # myArgs = ('y0', 'q') # myKW = {} # ---------------------------------------------------------------------- # Feed extra arguments manually and append even more from my list f("myEx", 4, 42, 420, *myList, *myDict, **myDict) # x = myEx # y = 4 # myArgs = (42, 420, 'Left', 'Right', 'Up', 'Down', 'Wubba', 'Dub') # myKW = {'Wubba': 'lubba', 'Dub': 'dub'} # ---------------------------------------------------------------------- # Without the stars, the entire provided list and dict become x, and y: f(myList, myDict) # x = ['Left', 'Right', 'Up', 'Down'] # y = {'Wubba': 'lubba', 'Dub': 'dub'} # myArgs = () # myKW = {} # ----------------------------------------------------------------------
**
사전 전용입니다.**
는 항상 *
뒤에 와야 합니다.TL;DR
다음은 Python 프로그래밍에서 *
및 **
에 대한 6가지 사용 사례입니다.
*args
: def foo(*args): pass
사용하여 임의의 수의 위치 인수를 허용하려면 여기서 foo
는 임의의 수의 위치 인수를 허용합니다. 즉, 다음 호출은 유효한 foo(1)
, foo(1, 'bar')
**kwargs
: def foo(**kwargs): pass
사용하여 임의의 수의 키워드 인수를 허용하려면 여기에서 'foo'는 임의의 수의 키워드 인수를 허용합니다. 즉, 다음 호출은 유효합니다 foo(name='Tom')
, foo(name='Tom', age=33)
*args, **kwargs
: def foo(*args, **kwargs): pass
사용하여 임의의 수의 위치 및 키워드 인수를 허용하려면 여기서 foo
는 임의의 수의 위치 및 키워드 인수를 허용합니다. 즉, 다음 호출은 유효한 foo(1,name='Tom')
, foo(1, 'bar', name='Tom', age=33)
*
사용하여 키워드 전용 인수를 적용하려면 : def foo(pos1, pos2, *, kwarg1): pass
, 여기서 *
는 foo가 pos2 이후의 키워드 인수만 허용한다는 것을 의미하므로 foo(1, 2, 3)
TypeError를 발생시키지만 foo(1, 2, kwarg1=3)
괜찮습니다.*_
사용하여 더 많은 위치 인수에 대한 관심을 표현하지 않으려면(참고: 이것은 단지 관례일 뿐입니다): def foo(bar, baz, *_): pass
는 (관례에 따라) foo
가 작업에서 bar
및 baz
인수만 사용한다는 것을 의미합니다. 다른 사람들을 무시할 것입니다.\**_
사용하여 더 이상 키워드 인수에 대한 관심을 표시하지 않으려면(참고: 이것은 관례일 뿐입니다): def foo(bar, baz, **_): pass
는 (관례에 따라) foo
bar
및 baz
인수만 사용함을 의미합니다. 작동하고 다른 사람들을 무시합니다. 보너스: 파이썬 3.8부터 /
를 사용하여 위치 전용 매개변수를 적용할 수 있습니다. 다음 예에서 매개변수 a 및 b는 위치 전용 이고 c 또는 d는 위치 또는 키워드일 수 있으며 e 또는 f는 키워드여야 합니다.
def f(a, b, /, c, d, *, e, f): pass
Python 문서에서:
형식 매개변수 슬롯보다 위치 인수가 더 많은 경우 "*identifier" 구문을 사용하는 형식 매개변수가 존재하지 않는 한 TypeError 예외가 발생합니다. 이 경우 형식 매개변수는 초과 위치 인수를 포함하는 튜플(또는 초과 위치 인수가 없는 경우 빈 튜플)을 받습니다.
키워드 인수가 형식 매개변수 이름과 일치하지 않으면 "**identifier" 구문을 사용하는 형식 매개변수가 없으면 TypeError 예외가 발생합니다. 이 경우 해당 형식 매개변수는 초과 키워드 인수(키워드를 키로 사용하고 인수 값을 해당 값으로 사용)를 포함하는 사전을 수신하거나, 초과 키워드 인수가 없는 경우 (새) 빈 사전을 수신합니다.
*
는 가변 인수를 튜플로 수신함을 의미합니다.
** 변수 인수를 사전으로 **
다음과 같이 사용됩니다.
1) 싱글 *
def foo(*args): for arg in args: print(arg) foo("two", 3)
산출:
two 3
2) 지금 **
def bar(**kwargs): for key in kwargs: print(key, kwargs[key]) bar(dic1="two", dic2=3)
산출:
dic1 two dic2 3
list
, dict
, tuple
및 set
디스플레이(때로는 리터럴이라고도 함)에서 이 구문을 사용할 수도 있습니다. PEP 488: 추가 풀기 일반화를 참조하십시오.
>>> (0, *range(1, 4), 5, *range(6, 8)) (0, 1, 2, 3, 5, 6, 7) >>> [0, *range(1, 4), 5, *range(6, 8)] [0, 1, 2, 3, 5, 6, 7] >>> {0, *range(1, 4), 5, *range(6, 8)} {0, 1, 2, 3, 5, 6, 7} >>> d = {'one': 1, 'two': 2, 'three': 3} >>> e = {'six': 6, 'seven': 7} >>> {'zero': 0, **d, 'five': 5, **e} {'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}
또한 단일 함수 호출에서 여러 iterable을 압축 해제할 수 있습니다.
>>> range(*[1, 10], *[2]) range(1, 10, 2)
(PEP 링크에 대해 mgilson에게 감사드립니다.)
다른 사람들이 언급하지 않은 예를 들어보고 싶습니다.
* 발전기의 포장을 풀 수도 있습니다.
Python3 문서의 예
x = [1, 2, 3] y = [4, 5, 6] unzip_x, unzip_y = zip(*zip(x, y))
unzip_x는 [1, 2, 3]이고 unzip_y는 [4, 5, 6]입니다.
zip()은 여러 개의 iretable 인수를 수신하고 생성기를 반환합니다.
zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))
nickd의 답변 을 바탕으로 ...
def foo(param1, *param2): print(param1) print(param2) def bar(param1, **param2): print(param1) print(param2) def three_params(param1, *param2, **param3): print(param1) print(param2) print(param3) foo(1, 2, 3, 4, 5) print("\n") bar(1, a=2, b=3) print("\n") three_params(1, 2, 3, 4, s=5)
산출:
1 (2, 3, 4, 5) 1 {'a': 2, 'b': 3} 1 (2, 3, 4) {'s': 5}
기본적으로 임의의 수의 위치 인수 가 *args를 사용할 수 있고 모든 명명된 인수 (또는 kwargs aka 키워드 인수)는 **kwargs를 사용할 수 있습니다.
함수에 전달된 인수를 함수 본문 내부에 각각 list
및 dict
다음과 같이 함수 서명을 정의할 때:
def func(*args, **kwds): # do stuff
임의의 수의 인수 및 키워드 인수를 사용하여 호출할 수 있습니다. 키워드가 아닌 인수는 함수 본문 내부의 args
라는 목록에 압축되고 키워드 인수는 함수 본문 내부의 kwds
func("this", "is a list of", "non-keyowrd", "arguments", keyword="ligma", options=[1,2,3])
이제 함수 본문 내부에는 함수가 호출될 때 값이 ["this", "is a list of", "non-keyword", "arguments"]
args
와 kwds
라는 두 개의 지역 변수가 있습니다. A는 dict
갖는 값 {"keyword" : "ligma", "options" : [1,2,3]}
이것은 또한 반대로, 즉 호출자 측에서 작동합니다. 예를 들어 다음과 같이 정의된 함수가 있는 경우
def f(a, b, c, d=1, e=10): # do stuff
호출 범위에 있는 이터러블 또는 매핑을 풀어서 호출할 수 있습니다.
iterable = [1, 20, 500] mapping = {"d" : 100, "e": 3} f(*iterable, **mapping) # That call is equivalent to f(1, 20, 500, d=100, e=3)
함수 호출 외에도 *args 및 **kwargs는 클래스 계층에 유용하며 Python에서 __init__
Django 코드와 같은 프레임워크에서도 비슷한 사용법을 볼 수 있습니다.
예를 들어,
def __init__(self, *args, **kwargs): for attribute_name, value in zip(self._expected_attributes, args): setattr(self, attribute_name, value) if kwargs.has_key(attribute_name): kwargs.pop(attribute_name) for attribute_name in kwargs.viewkeys(): setattr(self, attribute_name, kwargs[attribute_name])
그러면 하위 클래스가 될 수 있습니다.
class RetailItem(Item): _expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin'] class FoodItem(RetailItem): _expected_attributes = RetailItem._expected_attributes + ['expiry_date']
그런 다음 하위 클래스는 다음과 같이 인스턴스화됩니다.
food_item = FoodItem(name = 'Jam', price = 12.0, category = 'Foods', country_of_origin = 'US', expiry_date = datetime.datetime.now())
또한 해당 하위 클래스 인스턴스에만 의미가 있는 새 속성을 가진 하위 클래스는 기본 클래스 __init__
을 호출하여 속성 설정을 오프로드할 수 있습니다. 이것은 *args 및 **kwargs를 통해 수행됩니다. kwargs는 주로 명명된 인수를 사용하여 코드를 읽을 수 있도록 사용됩니다. 예를 들어,
class ElectronicAccessories(RetailItem): _expected_attributes = RetailItem._expected_attributes + ['specifications'] # Depend on args and kwargs to populate the data as needed. def __init__(self, specifications = None, *args, **kwargs): self.specifications = specifications # Rest of attributes will make sense to parent class. super(ElectronicAccessories, self).__init__(*args, **kwargs)
다음과 같이 나타낼 수 있습니다.
usb_key = ElectronicAccessories(name = 'Sandisk', price = '$6.00', category = 'Electronics', country_of_origin = 'CN', specifications = '4GB USB 2.0/USB 3.0')
전체 코드는 여기
*args
및 **kwargs
: 다양한 수의 인수를 함수에 전달할 수 있습니다.
*args
: 키워드가 지정되지 않은 가변 길이 인수 목록을 함수에 보내는 데 사용됩니다.
def args(normal_arg, *argv): print("normal argument:", normal_arg) for arg in argv: print("Argument in list of arguments from *argv:", arg) args('animals', 'fish', 'duck', 'bird')
생산할 것:
normal argument: animals Argument in list of arguments from *argv: fish Argument in list of arguments from *argv: duck Argument in list of arguments from *argv: bird
**kwargs*
**kwargs
사용하면 키워드가 지정된 가변 길이 인수를 함수에 전달할 수 있습니다. 함수에서 명명된 인수를 처리하려면 **kwargs
def who(**kwargs): if kwargs is not None: for key, value in kwargs.items(): print("Your %s is %s." % (key, value)) who(name="Nikola", last_name="Tesla", birthday="7.10.1856", birthplace="Croatia")
생산할 것:
Your name is Nikola. Your last_name is Tesla. Your birthday is 7.10.1856. Your birthplace is Croatia.
3개의 항목을 인수로 갖는 함수가 주어졌을 때
sum = lambda x, y, z: x + y + z sum(1,2,3) # sum 3 items sum([1,2,3]) # error, needs 3 items, not 1 list x = [1,2,3][0] y = [1,2,3][1] z = [1,2,3][2] sum(x,y,z) # ok sum(*[1,2,3]) # ok, 1 list becomes 3 items
삼각형, 원 및 직사각형 항목의 가방이있는이 장난감을 상상해보십시오. 그 가방은 직접 맞지 않습니다. 이 3개의 항목을 가져오려면 가방의 포장을 풀어야 하며 이제 적합합니다. Python * 연산자는 이 압축 풀기 프로세스를 수행합니다.
함수에서 둘 다 사용하는 좋은 예는 다음과 같습니다.
>>> def foo(*arg,**kwargs): ... print arg ... print kwargs >>> >>> a = (1, 2, 3) >>> b = {'aa': 11, 'bb': 22} >>> >>> >>> foo(*a,**b) (1, 2, 3) {'aa': 11, 'bb': 22} >>> >>> >>> foo(a,**b) ((1, 2, 3),) {'aa': 11, 'bb': 22} >>> >>> >>> foo(a,b) ((1, 2, 3), {'aa': 11, 'bb': 22}) {} >>> >>> >>> foo(a,*b) ((1, 2, 3), 'aa', 'bb') {}
*args
, **kwargs
및 super
및 상속을 한 번에 기억하는 데 도움이 됩니다.
class base(object): def __init__(self, base_param): self.base_param = base_param class child1(base): # inherited from base class def __init__(self, child_param, *args) # *args for non-keyword args self.child_param = child_param super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg class child2(base): def __init__(self, child_param, **kwargs): self.child_param = child_param super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg c1 = child1(1,0) c2 = child2(1,base_param=0) print c1.base_param # 0 print c1.child_param # 1 print c2.base_param # 0 print c2.child_param # 1
**
포장 풀기이 스레드의 답변 외에도 다른 곳에서 언급되지 않은 또 다른 세부 사항이 있습니다. 이것은 Brad 솔로몬 의 답변을 확장합니다.
**
str.format
python str.format을 사용할 때 유용합니다.
f-strings
f- 문자열로 할 수 있는 것과 다소 비슷하지만 변수를 보유하기 위해 사전을 선언하는 오버헤드가 추가됩니다(f-문자열에는 사전이 필요하지 않음).
## init vars ddvars = dict() ddcalc = dict() pass ddvars['fname'] = 'Huomer' ddvars['lname'] = 'Huimpson' ddvars['motto'] = 'I love donuts!' ddvars['age'] = 33 pass ddcalc['ydiff'] = 5 ddcalc['ycalc'] = ddvars['age'] + ddcalc['ydiff'] pass vdemo = [] ## ******************** ## single unpack supported in py 2.7 vdemo.append(''' Hello {fname} {lname}! Today you are {age} years old! We love your motto "{motto}" and we agree with you! '''.format(**ddvars)) pass ## ******************** ## multiple unpack supported in py 3.x vdemo.append(''' Hello {fname} {lname}! In {ydiff} years you will be {ycalc} years old! '''.format(**ddvars,**ddcalc)) pass ## ******************** print(vdemo[-1])
*args (또는 *any)는 모든 매개변수를 의미합니다.
def any_param(*param): pass any_param(1) any_param(1,1) any_param(1,1,1) any_param(1,...)
주의사항 : *args에 매개변수를 전달할 수 없습니다.
def any_param(*param): pass any_param() # will work correct
*args는 유형 튜플에 있습니다.
def any_param(*param): return type(param) any_param(1) #tuple any_param() # tuple
요소에 액세스하려면 *를 사용하지 마십시오.
def any(*param): param[0] # correct def any(*param): *param[0] # incorrect
**kwd
**kwd 또는 **any 이것은 dict 유형입니다
def func(**any): return type(any) # dict def func(**any): return any func(width="10",height="20") # {width="10",height="20")
def foo(param1, *param2):
*param2
대해 임의의 수의 값을 허용할 수 있는 메서드입니다.def bar(param1, **param2):
*param2
대한 키를 사용하여 임의의 수의 값을 허용할 수 있는 메서드입니다.param1
은 단순 매개변수입니다.예를 들어 Java에서 varargs 를 구현하기 위한 구문은 다음과 같습니다.
accessModifier methodName(datatype… arg) { // method body }
출처 : http:www.stackoverflow.com/questions/36901/what-does-double-star-asterisk-and-star-asterisk-do-for-parameters
내 JavaScript 코드는 "요청된 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다" 오류를 수신하지만 Postman은 그렇지 않은 이유는 무엇입니까? (0) | 2021.11.10 |
---|---|
Windows에 pip를 어떻게 설치합니까? (0) | 2021.11.10 |
JavaScript에서 URL을 인코딩하시겠습니까? (0) | 2021.11.10 |
글머리 기호가 없는 순서 없는 목록이 필요합니다. (0) | 2021.11.10 |
인스턴스 상태 저장을 사용하여 활동 상태를 저장하려면 어떻게 해야 합니까? (0) | 2021.11.10 |