0

So, basically my python wrapper is not working because it's not identifying an import statement I used at the start of my code. Here's my code:

# Decorator para imprimir o tempo de execução de uma função
import functools
import time 

def timer(func):
    @functools.wraps(func)
    def timer_wrapper(*args, **kwargs):
        start_time = time.perf_counter()
        value = func(*args, **kwargs)
        end_time = time.perf_counter()
        time = end_time - start_time
        print(f'Finished {func.__name__} in {time:.4f} secs')
        return value
    return timer_wrapper

@timer
def some_func(n):
    time.perf_counter
    for i in range(n):
        sum([ j*2 for j in range(n)])

some_func(121)

Here's the exception:

Traceback (most recent call last):
  File "decorator.py", line 22, in <module>
    some_func(121)
  File "decorator.py", line 9, in timer_wrapper
    start_time = time.perf_counter()
UnboundLocalError: local variable 'time' referenced before assignment

Oddilly enough, it works inside other functions(see some_func()).

What's going on? My python version is 3.8.10

Luiz
  • 99
  • 5
  • 2
    Writing `time = end_time - start_time` makes `time` a local variable and therefore **not** a reference to the `time` module (which, when you do `import time` at the top of the file, *becomes a global variable*). This means you encounter the problem described in the linked duplicate. – Karl Knechtel Oct 27 '21 at 01:14

1 Answers1

1

Within the function body, you can't use time as both as a global variable:

start_time = time.perf_counter()  # line 1 of the function

And as a local variable:

time = end_time - start_time  # line 4 of the function

In order to compile the code of the function, Python has to determine what the local variable names are. The presence of the assignment statement above makes time into a local variable at function definition time. This means that it's already considered a local variable when the first line of the function is executed, even though it hasn't been assigned to yet.

Here is a minimal reproduction of the problem:

>>> import time
>>> def foo():
...     t = time.time()
...     time = t
... 
>>> foo.__code__.co_varnames
('time', 't')
>>> foo()
# UnboundLocalError: local variable 'time' referenced before assignment

Instead, use a different local variable name, like elapsed. The answer on the duplicate suggesting to use a global statement is not a good answer here.

wim
  • 338,267
  • 99
  • 616
  • 750