2017-12-31 136 views
1

작성하는 방법은 매우 간단하지만 예외를 처리해야하는 메서드가 많이 있습니다. 예외 관리는 항상 동일하므로 래퍼를 함수로 작성하여 특정 함수 호출 인스턴스를 매개 변수로 호출해야합니다. 가능한가? 이 라인을 따라인수로 함수를 인수로 전달하는 방법

뭔가 (이 비 작동 일러스트 레이 션) :

def g(h): 
    while True: 
     try: 
      x = h() 
     except: 
      # got an error 
      print ("Unexpected error. Retry.") 
     else: 
      # everything is fine 
      return x 

def f1(x): 
    # do something that may fail (e.g. access a distant server) 
    y = (...whatever...) 
    return y 

def f2(x,y): 
    # do something else that may fail (e.g. access a distant server, but different request) 
    z = (...whatever...) 
    return z 

print (g(f1(3))) 
print (g(f1(6))) 
print (g(f2(5,'abc'))) 

참고 : 나는 클래스 정의를 필요로하지 않는 대답을 찾고 있어요. 또한 파이썬에서 람다 함수에 익숙하지 않지만 솔루션의 일부가 될 수 있을까요?

+0

g 성공할 때까지 돌아 가지 않을 것입니다. –

+0

예, 정확하게. 나는 그것을 언급 했어야했다. 실제로, 나는 최대 시도 횟수 측면에서 타임 아웃을 구현한다. 코드에서 – nekonaute

+0

- 왜 작동하지 않습니까? havent는 아직 pyfiddle에 게시했지만, 합법적 인 것으로 보인다. - g ::에는''args''와'** kwargs''가 필요합니다. (https://stackoverflow.com/questions/36901/) 별표 - 별표 - 별표 - 매개 변수)를 사용하여'g '가'g (f1,3)'과 같은 종류의 추가 매개 변수를 취하도록 허용합니다. 'g'는 주어진 함수에 물건을 전달해야합니다 .... –

답변

1

첫 번째 함수에서 함수를 반환해야합니다. 내가 인수의 가변 수를 허용하기 위해 * 연산자를 사용하고

def g(h): 
    def f(*arguments): 
     try: 
      x = h(*arguments) 
     except: 
      # got an error 
      print ("Unexpected error. Retry.") 
     else: 
      # everything is fine 
      return x 
    return f 

: https://docs.python.org/3/tutorial/controlflow.html#arbitrary-argument-lists

당신이 함수 h와 g를 호출 할 때마다, 일부 인수 부르는 경우 것입니다 당신이 함수를 반환합니다 같은 인수를 사용하여 h를 호출하십시오 (그러나 오류 처리 내부).

이제 함께 사용할 수 있습니다

g(f1)(3) 

또는 새 함수를 만드는 방지하기 위해 g 방식에서 직접 * 연산자를 사용할 수 있습니다.

def g(h, *arguments): 
    try: 
     x = h(*arguments) 
    except: 
     # got an error 
     print ("Unexpected error. Retry.") 
    else: 
     # everything is fine 
     return x 

그러면 그런 식으로 부를 것이다 : 나는 첫 번째 대안 청소기를 찾을

g(f1, 3, 4) 

당신이 안전 기능을 가질 수 있습니다, 특히 있기 때문에, 당신은 조작 것 :

safe_f1 = g(f1) 
safe_f1(3) 
+2

감사합니다! 그것은 작동합니다 (나의 평판은 <15,하지만 나는 당신의 대답을 밀어 냈습니다). – nekonaute

+1

나는 그것을 너에게 주겠다 @nekonaute –

1

이 힘을 도움 :

데코레이터 사용

def exception_handler_wrapper(fn): 
    def new_fn(*args, **kwargs): 
     try: 
      result = fn(*args, **kwargs) 
     except Exception as e: 
      # return error string or print error string or log error string 
      # or do whatever suits you, with the exception 
      return "Error occured:" + str(e) 
     else: 
      return result 
    return new_fn 


@exception_handler_wrapper 
def f1(x): 
    # do something that may fail (e.g. access a distant server) 
    # emulating something that may fail: 
    if x % 2 == 0: 
     return "success" 
    else: 
     raise ValueError("x not even") 


@exception_handler_wrapper 
def f2(x, y): 
    # do something else that may fail (e.g. access a distant server, but 
    # different request) 
    # emulating something that may fail: 
    if x != 0 or y != 'abc': 
     return "success" 
    else: 
     raise Exception("Sum not 100") 

print("Expression f1(3):", f1(3)) 
print("Expression f1(6):", f1(6)) 
print("Expression f2(5, 'abc'):", f2(5, 'abc')) 

(10)과 출력했다 : 예외 당신이 처리하고자하는 모든 기능이 def inition 그리고 당신이 단지와 같은 이름을 호출하는 일반적 대신에 함수를 호출하기 전에 단지 @exception_handler_wrapper 장소와 지금

Expression f1(3): Error happend:x not even 
Expression f1(6): success 
Expression f2(5, 'abc'): success 

: g(f1(6)).