파이썬에서 ** kwargs를 사용하는 이유는 무엇입니까? 명명 된 인수를 사용하는 것보다 실질적인 이점은 무엇입니까?
나는 정적 언어의 배경에서 왔습니다. 누군가 명명 된 인수에 비해 ** kwargs를 사용할 때의 실제 이점을 설명 할 수 있습니까 (이상적으로는 예제를 통해) ?
나에게 그것은 단지 함수 호출을 더 모호하게 만드는 것 같습니다. 감사.
실제 사례 :
데코레이터-일반적으로 일반적이므로 인수를 미리 지정할 수 없습니다.
def decorator(old):
def new(*args, **kwargs):
# ...
return old(*args, **kwargs)
return new
알 수없는 수의 키워드 인수로 마술을하고 싶은 곳. Django의 ORM은이를 수행합니다. 예 :
Model.objects.filter(foo__lt = 4, bar__iexact = 'bar')
일련의 이유로 거의 임의의 명명 된 인수를 받아들이고 싶을 수 있습니다. 이것이 **kw양식에서 할 수있는 것입니다.
가장 일반적인 이유는 래핑하는 다른 함수에 바로 인수를 전달하는 것입니다 (데코레이터는 이것의 한 경우이지만 유일한 경우는 먼!)-이 경우 **kw래퍼와 래피 간의 결합을 느슨하게합니다. 랩퍼는 랩 피의 모든 인수를 알거나 신경 쓸 필요가 없습니다. 완전히 다른 또 다른 이유가 있습니다.
d = dict(a=1, b=2, c=3, d=4)
모든 이름을 미리 알려야한다면 분명히이 접근 방식은 존재할 수 없었습니다. 그리고 btw, 해당되는 경우 키가 리터럴 문자열 인 dict를 만드는 방법을 다음과 같이 선호합니다.
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
후자는 문장 부호가 많고 가독성이 떨어지기 때문입니다.
수락하는 훌륭한 이유가 **kwargs적용되지 않는 경우 수락하지 마십시오. 그렇게 간단합니다. IOW, 호출자가 임의의 이름으로 추가 명명 된 인수를 전달하도록 허용 할 합당한 이유가없는 경우, 그런 일이 발생하지 않도록 **kw하십시오 def. 명령문 의 함수 서명 끝에 양식을 넣지 마십시오 .
에 관해서는 사용하여 **kw 호출에, 그건 당신이 함께 당신이 다음 독립적으로 단일 통화 점의하는 딕셔너리에 해당하는 값으로, 각각을 통과 단일 호출 시점에서 딕셔너리를 사용해야합니다 명명 된 인수의 정확한 세트를 넣을 수 있습니다. 비교:
if x: kw['x'] = x
if y: kw['y'] = y
f(**kw)
에:
if x:
if y:
f(x=x, y=y)
else:
f(x=x)
else:
if y:
f(y=y)
else:
f()
두 가지 가능성 (그리고 가장 단순한 종류!)에도 불구 **kw하고, 두 번째 옵션은 절대적으로 견딜 수없고 참을 수 없게 만드는 것이 부족 합니다. 가능성이 6 개일 때, 아마도 약간 더 풍부한 상호 작용에서 어떻게 진행되는지 상상해보십시오. .없이 **kw, 삶은 그러한 상황에서 절대 지옥이 될 것입니다!
**kwargs(및 *args) 사용하려는 또 다른 이유 는 하위 클래스의 기존 메서드를 확장하는 경우입니다. 기존의 모든 인수를 수퍼 클래스의 메서드에 전달하고 싶지만 향후 버전에서 서명이 변경 되더라도 클래스가 계속 작동하도록하고 싶습니다.
class MySubclass(Superclass):
def __init__(self, *args, **kwargs):
self.myvalue = kwargs.pop('myvalue', None)
super(MySubclass, self).__init__(*args, **kwargs)
두 가지 일반적인 경우가 있습니다.
첫째 : 여러 키워드 인자를받는 또 다른 함수를 래핑하고 있지만, 그냥 전달할 것입니다.
def my_wrapper(a, b, **kwargs):
do_something_first(a, b)
the_real_function(**kwargs)
둘째 : 객체에 속성을 설정하는 등의 키워드 인수를 기꺼이 허용합니다.
class OpenEndedObject:
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
foo = OpenEndedObject(a=1, foo='bar')
assert foo.a == 1
assert foo.foo == 'bar'
**kwargs매개 변수의 이름을 미리 모르면 좋습니다. 예를 들어 dict생성자는이를 사용하여 새 사전의 키를 초기화합니다.
dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)
In [3]: dict(one=1, two=2)
Out[3]: {'one': 1, 'two': 2}
다음은 CGI Python에서 사용한 예입니다. 함수 **kwargs를 사용 하는 클래스를 만들었습니다 __init__. 이를 통해 서버 측에서 클래스를 사용하여 DOM을 에뮬레이션 할 수있었습니다.
document = Document()
document.add_stylesheet('style.css')
document.append(Div(H1('Imagist\'s Page Title'), id = 'header'))
document.append(Div(id='body'))
유일한 문제는 classPython 키워드 이기 때문에 다음을 수행 할 수 없다는 것 입니다.
Div(class = 'foo')
해결책은 기본 사전에 액세스하는 것입니다.
Div(**{'class':'foo'})
이것이 기능의 "올바른"사용법이라고 말하는 것이 아닙니다. 제가 말하는 것은 이와 같은 기능을 사용할 수있는 모든 종류의 예상치 못한 방법이 있다는 것입니다.
또 다른 전형적인 예가 있습니다.
MESSAGE = "Lo and behold! A message {message!r} came from {object_} with data {data!r}."
def proclaim(object_, message, data):
print(MESSAGE.format(**locals()))
One example is implementing python-argument-binders, used like this:
>>> from functools import partial >>> def f(a, b): ... return a+b >>> p = partial(f, 1, 2) >>> p() 3 >>> p2 = partial(f, 1) >>> p2(7) 8
This is from the functools.partial python docs: partial is 'relatively equivalent' to this impl:
def partial(func, *args, **keywords): def newfunc(*fargs, **fkeywords): newkeywords = keywords.copy() newkeywords.update(fkeywords) return func(*(args + fargs), **newkeywords) newfunc.func = func newfunc.args = args newfunc.keywords = keywords return newfunc
'program story' 카테고리의 다른 글
| 나뭇 가지 템플릿에서 돈 서식 지정 (0) | 2020.11.23 |
|---|---|
| Java는 사용 가능한 메모리를 얻습니다. (0) | 2020.11.23 |
| .NET에서 프로그래밍 방식으로 Windows 서비스를 다시 시작하는 방법 (0) | 2020.11.23 |
| 새로 설치 한 후 Postgresql에 어떻게 로그인하고 인증합니까? (0) | 2020.11.23 |
| 'cpan'을 통해 설치된 Perl 모듈을 어떻게 제거 할 수 있습니까? (0) | 2020.11.23 |