Shailab Singh Shailab Singh - 27 days ago 6
Python Question

Trying to use variables outside of a for loop gives a SyntaxError: no binding for nonlocal 'max_' found

def min_diff(arry_):
max_ =0
temp_ =0
for i in arry_:
nonlocal max_
nonlocal temp_
if i > max_:
nonlocal max_
nonlocal temp_
temp_ = max_
max_ =i
return max_-temp_


I want to use
max_
and
temp_
outside the loop but I am getting an error

SyntaxError: no binding for nonlocal 'max_' found

Answer

nonlocal can only applied in functions that have a nested scope. You only get a nested scope when you define your function inside of another function.

Python doesn't have block scopes; the for loop doesn't create a new scope, so you don't need to use nonlocal in a loop. Your variables are available throughout the rest of the function. Just drop the nonlocal statements altogether:

def min_diff(arry_):
    max_ = 0
    temp_ = 0
    for i in arry_:
        if i > max_:
            temp_ = max_
            max_ = i
    return max_ - temp_

In Python, only functions, class definitions and comprehensions (list, set, and dict comprehensions as well as generator expressions) get their own scope, and only functions can act as a parent scope for closures (nonlocal variables).

There is also a bug in your code; if you pass in a list where the first value is also the maximum value in the list, temp_ is set to 0 and then never changes. You won't ever find the second-highest value in that case, because only for the very first i will if i > max_: be true. You'd also need to test if i is greater than temp_ in that case:

def min_diff(arry_):
    max_ = 0
    temp_ = 0
    for i in arry_:
        if i > max_:
            temp_ = max_
            max_ = i
        elif i > temp_:
            temp_ = i
    return max_ - temp_

As a side note: you don't need to use trailing underscores in your local variables. Of all the local names used, only max_ would potentially shadow the built-in max() function, but since you don't use that function at all, using max_ instead of max in your function is not actually a requirement. I'd personally drop all the trailing _ underscores from all the names in the function. I'd also use different names; perhaps highest and secondhighest.

Comments