0

here is my decorator for recall func when func return is not True

def deco_retry(retry_times):
    def _deco_retry(func):
        def wrapper(*args, **kwargs):
            while retry_times > 0:
                ret = func(*args, **kwargs)
                if ret:
                    return ret
                retry_times -= 1
        return wrapper
    return _deco_retry

@deco_retry(retry_times=1)
def func(ok=1):
    if ok == 1:
        return True
    else:
        return False

when i call func(), error occurred:

Traceback (most recent call last):
  File "E:/Charles/Code/pycharmprj/Huobi/test_code/decorator_test.py", line 26, in <module>
    func()
  File "E:/Charles/Code/pycharmprj/Huobi/test_code/decorator_test.py", line 10, in wrapper
    while retry_times > 0:
UnboundLocalError: local variable 'retry_times' referenced before assignment

why can't i reference retry_times in the innermost function: wrapper, how can i correct this error?

melpomene
  • 84,125
  • 8
  • 85
  • 148
Charles
  • 5
  • 2
  • This has nothing to do with decorators. This is the standard problem of Python creating a local variable for any name that is assigned to within a function. – melpomene Jul 02 '18 at 01:04
  • thank you! I know the reason that I create a new local variable – Charles Jul 02 '18 at 05:51

1 Answers1

2

This is because you are re-assigning retry_times later in the function with retry_times -= 1, hence making it a local variable.

You can add nonlocal (if python3) right above the while loop:

def _deco_retry(func):
    def wrapper(*args, **kwargs):
        nonlocal retry_times
        while retry_times > 0:

Or instead of using a while loop, you can try looping with range instead:

def wrapper(*args, **kwargs):
    for _ in range(retry_times):
        ret = func(*args, **kwargs)
        if ret:
            return ret

Should work the same, and you don't have to mess around with adding/subtracting the amount of retries.

salparadise
  • 5,699
  • 1
  • 26
  • 32
  • Thank you very much, When I correct to the same as you, the problem was solved. and I know I am wrong because I created a new local variable. – Charles Jul 02 '18 at 05:51