'How to define a counter of another function in a Python decorator?

I implement finding the roots of an equation with one variable by the dichotomy method. There's the essence: the segment is divided in half several times. If the function in the middle of the segment is zero or less than the specified error, the root is found. Otherwise, we continue the division, and the left and right "boundaries" of the segment are taken as the boundaries of the segment.

The output of the results is organized in a wrapper function so that this output functionality does not affect the calculation of the execution time of the main task - root search.

It is required, among other things, to specify the number of iterations (how many times the segment was divided in half). As I have done now (and I understand myself that it is wrong), it does not work. Mistake:

NameError: name 'counter' is not defined

What should I do? Code:

import numpy as np

def print_dichotomy(dichotomy):
    def wrapper(a,b,n, eps):
        print('The roots according to the dichotomy method are located at points:')
        print(', '.join(map(lambda x: f'{x:.4f}', res)))
        print('Number of iterations: ', counter)   # THERE IS A MISTAKE HERE
    return wrapper

def f(x):
    return 1.2-np.log(x)-4*np.cos(2*x)

@print_dichotomy
def dichotomy (a,b,n, eps): # the segment from a to b is divided into n parts, the eps error
    """
    The function of separating and clarifying the root
    """
    assert a!=0,  'a is 0'
    assert b!=0, 'b is 0'
    
    # first we separate the roots
    grid=np.linspace(a, b, n)
    
    # let 's clarify the roots
    counter=0
    for x,y in zip(grid, grid[1:]):
        if f(x) * f(y) > 0: # if there is no root on the segment, look at the following
            continue
        root = None
        while ( abs(f(y)-f(x)) )>eps:     # while the segment is larger than the specified error, we perform the following operations:
            mid = (y+x)/2                   # we get the middle of the segment
            if f(mid) == 0 or f(mid)<eps:    # if the function in the middle of the segment is zero or less than the error:
                root = mid                  # the root is equal to the mean value
                counter+=1
                break
            elif (f(mid) * f(x)) < 0:       # otherwise, if the product of the function in the middle of the segment by the function at point a <0
                y = mid                     # the point b becomes the middle
            else:
                x = mid                     #in another case, point a
        if root:
            yield root


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source