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
.
Last but not least, you could just use the heapq.nlargest()
function to get those two largest values, efficiently:
from heapq import nlargest
def min_diff(values):
highest, secondhighest = nlargest(2, values)
return highest - secondhighest
You may want to add some length checks there; if len(values) < 2
is true, what should happen instead?