2012-06-05 3 views
7

이 다른 행동 ::키워드 인수에 전달

>> def minus(a, b): 
>> return a - b 

>> minus(**dict(b=2, a=1)) 
-1 

>> int(**dict(base=2, x='100')) 
4 

>> import operator 
>> operator.sub.__doc__ 
'sub(a, b) -- Same as a - b.' 
>> operator.sub(**dict(b=2, a=1)) 
TypeError: sub() takes no keyword arguments 

operator.sub 어떻게 동작 int(x, [base]) 다르게 수행을 고려할 때이 두 가지 내장 기능이 서로 다른 행동 이유를 설명하세요?

+3

사람들이이 함수가 키워드 인수를 사용하지 않기로 선택한 이유에 대해 사람들이 대답 할 수 있다면 좋을 것입니다. D – jamylak

답변

7

구현 세부 사항입니다. Python C API to retrieve arguments은 위치 인수와 키워드 인수를 구분합니다. 위치 적 주장은 내부적으로 이름조차 갖지 못한다. 당신이 볼 수 있듯이

PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2) 

, 그것은 어떤 인수 이름을 포함하지 않습니다

operator.add 기능 (및 sub 같은 유사한 것)의 인수를 검색하는 데 사용되는 코드는 다음입니다. operator.add 관련 전체 코드는 다음과 같습니다

#define spam2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \ 
    PyObject *a1, *a2; \ 
    if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \ 
    return AOP(a1,a2); } 

spam2(op_add   , PyNumber_Add) 
#define spam2(OP,ALTOP,DOC) {#OP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)}, \ 
          {#ALTOP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)}, 
spam2(add,__add__, "add(a, b) -- Same as a + b.") 

당신이 볼 수 있듯이, ab는 문서화 문자열에 사용되는 유일한 장소. 메서드 정의는 메서드가 키워드 인수를 받아들이는 데 필요한 METH_KEYWORDS 플래그도 사용하지 않습니다.

일반적으로 말해, 당신은 안전하게 인수 이름 항상 키워드 인수를 받아 들일 것입니다 알고있는 파이썬 기반의 기능은 (물론 사람이 *args 풀고 있지만 인수가 보이는 함수 문서를 만드는 더러운 물건을 할 수 있다고 가정 할 수있다 normal) C 함수는 키워드 인수를 허용하거나 허용하지 않을 수 있습니다. 몇 가지 인수 또는 선택적 인수 이상을 포함하는 함수가 이후/선택적 인수에 대한 키워드 인수를 허용 할 가능성이 있습니다. 하지만 당신은 꽤 많이 테스트해야합니다.

python-ideas mailinglist에서 키워드 인수 지원에 대한 토론을 찾을 수 있습니다.

흠 : 거기에 귀도 반 로섬 (Guido van Rossum)에서 문 (파이썬의 창조자 일명 Benevolent Dictator For Life)도 있습니다. 많은 (대부분?) 1-arg와 선택된 2-arg 함수 (그리고 거의 3 + -arg 함수)는 가독성을 떨어 뜨릴 것이라고 생각합니다. 예를 들어 ord (char = x)의 이 나타났습니다.

나는 실제로 인수 이 (우리가 이미 그것이 키워드를해야한다는 것은 구문을 추가하는 것처럼) 키워드 인수로 제공 할 수없는 상태로 통 사적 기능을보고 싶습니다.

키워드를 추가 할 때 args가 잘못 입력 된 부분이 있습니다. 기본 제공 유형 또는 ABC가 있으며 재정의 할 수 있습니다. 예 : dict에 pop() 메소드를 고려하십시오.인수 이름이 현재 문서화되지 않았으므로 다른 사람이 dict을 하위 클래스로 지정하고이 메소드를 무시하면 이 무엇인지는 중요하지 않습니다. dict을 사용하여 dict을 에뮬레이션하려는 다른 변경 가능한 매핑 클래스를 만드는 경우 모든 호출자 (dict, dict 하위 클래스 또는 dict-like 오리를 예상 함)는 호출에서 위치 인수를 사용합니다. 그러나 우리가 인데 pop()에 대한 인수 이름을 문서화하고 사용자가 을 사용하기 시작하면 대부분의 dict 하위 클래스와 오리가 갑자기 깨져서 (운이 좋으면 같은 이름을 선택했습니다).

+0

+1 내 질문에 너무 대답합니다! – jamylak

+0

문체 선택 이외에도, 키워드 인수를 받아들이면 함수 호출에 오버 헤드가 추가되고 사용자가 실제로 인수를 키워드로 내장 함수에 전달하면 오버 헤드가 상당히 증가한다는 점을 지적해야합니다. 파이썬 3.5에서 마이크로 벤치 마크는'int ("0", 2)'와'int ("0", base = 2)'에 대해 내 컴퓨터에서 실행하는 데 ~ 2.5 배의 시간이 걸린다. 실제 작업보다 구문 분석에 더 많은 시간이 소요됩니다. 더 나쁜 것은 인수가 하나 인 인수를 취하는 것으로, 인수의 줄 바꿈을 피하는 빠른 경로가 있지만 키워드로 이동하면 인수가'튜플 및/또는'dict '에 래핑되어야 함을 의미합니다. – ShadowRanger

3

minus(**dict(b=2, a=1))minus(b=2, a=1)으로 확장됩니다. 이 정의는 인수 이름이 a이고 b이기 때문에 작동합니다.

operator.sub(**dict(b=2, a=1))operator.sub(b=2, a=1)으로 확장됩니다. sub는 키워드 인수를 허용하지 않기 때문에 작동하지 않습니다.

+2

나는 키워드 인수를 받아들이지 않는 이유를 묻고 있습니다. 대답하지 않았습니다. – jamylak

+0

operator.sub가 'minus'와 같은 인수를 갖고 있지 않다는 말입니까? – canadadry

+0

@ 본미 : 맞습니다. 'operator.sub'의 인수는 이름이 없습니다 – Eric

4

operatordefines functions differently 인 C 모듈입니다. 모듈 초기화의 함수 선언에 METH_KEYWORDS이 포함되어 있지 않으면이 함수는 모든 조건에서 키워드 인수를 허용하지 않으며 질문에 제공된 오류가 발생합니다.

관련 문제