2009-06-01 3 views
1

잘못된 수의 인수 또는 정의에없는 키워드 인수를 사용하여 함수를 호출하면 TypeError가 발생합니다. 콜백을 지원하고 가변 인수를 사용하여 코드를 호출하는 코드를 원합니다. 한 가지 방법은 콜백 cb에 대해 cb.__code__.cb_argcountcb.__code__.co_varnames을 사용하는 것입니다. 그러나 나는 이것을 apply과 같은 것으로 추상화 할 것이지만 "적합"한 인수 만 적용합니다. 예를 들어TypeError를 호출하지 않고 잘못된 수의 인수로 파이썬 함수를 호출 할 수 있습니까?

:

def foo(x,y,z): 
    pass 

cleanvoke(foo, 1)   # should call foo(1, None, None) 
cleanvoke(foo, y=2)  # should call foo(None, 2, None) 
cleanvoke(foo, 1,2,3,4,5) # should call foo(1, 2, 3) 
          # etc. 

이미 파이썬에서이 같은 일이 있나요, 아니면 내가 처음부터 작성해야 뭔가?

답변

7

직접 내용을 파고 들지 말고 inspect 함수의 서명 - 아마도 inspect.getargspec(cb)을 원할 수 있습니다.

함수를 "적절하게"호출하기 위해 해당 정보와 args를 정확히 사용하는 방법은 완전히 명확하지 않습니다.

args = inspect.getargspec(cb)[0] 
cb(**dict((a,d.get(a)) for a in args)) 

은 어쩌면 당신은 애호가 뭔가를 원하고, 정확히 무엇에 정교한 수 있습니다 ... 당신은 단순한 이름 인수에 관심, 그리고 당신이 전달하고자하는 값이 DICT d에 단순화를 위해 가정?

+0

getargspec은 (__magic__ 물건을 볼 필요가 없습니다 예를 들어,). 필자가 제안한대로 ("a"오타가 아닌 "k"가 아닌) args라는 이름의 필터를 사용하려고합니다. 길이가 아닌 일반 args - 호출에 인수가 충분하지 않으면 None을 채우고 여분을 잘라냅니다 인수. 어쩌면 나는 장식 자로도 만들 것이다. :) –

+0

두 번째 생각에, 당신은 내가 이것을 아주 분명하게 만들지 않았 음이 틀림 없다 (내 머리 속에서도). 콜백은 디폴트, * args, ** kwargs의 다른 조합을 가지고 있습니다 ... –

+0

Heh, 오타가 수정되었습니다. 그것에 대해 더 생각해 본 결과 이름이 지정된 args에 중점을 두는 것이 좋은 생각이라고 생각합니다. 위치와 이름을 섞으면 항상 까다 롭습니다. 내 코드의 한 가지 중요한 개선 사항은 다음과 같습니다. 인수 a가 기본값을 가지며 d가 아닌 경우 내 코드가 (.get에 의해) 수행하지 않고 강제로 None으로 설정하십시오. –

3

아마도? 확실히이 저를 걱정 한 방법으로 더 많은 "깨끗한"할 것입니다

def fnVariableArgLength(*args, **kwargs): 
    """ 
    - args is a list of non keywords arguments 
    - kwargs is a dict of keywords arguments (keyword, arg) pairs 
    """ 
    print args, kwargs 


fnVariableArgLength() #() {} 
fnVariableArgLength(1, 2, 3) # (1, 2, 3) {} 
fnVariableArgLength(foo='bar') #() {'foo': 'bar'} 
fnVariableArgLength(1, 2, 3, foo='bar') # (1, 2, 3) {'foo': 'bar'} 

편집 귀하의 사용 사례

def foo(*args,*kw): 
    x= kw.get('x',None if len(args) < 1 else args[0]) 
    y= kw.get('y',None if len(args) < 2 else args[1]) 
    z= kw.get('z',None if len(args) < 3 else args[2]) 
    # the rest of foo 

foo(1)   # should call foo(1, None, None) 
foo(y=2)  # should call foo(None, 2, None) 
foo(1,2,3,4,5) # should call foo(1, 2, 3) 
+0

Nah, 충분히 명확하지 않은 것에 대해 유감스럽게 생각합니다. 나는 의미를 설명하기 위해 몇 가지 예를 추가했습니다. –