function inside a function - global and nonlocal scope - python

I'm trying out the following code with global, and nonlocal scope. following snippet working wihtout any issues.
def countdown(start):
n = start
def display():
print('--> %d' % n)
def decrement():
nonlocal n ##using python3
n -= 1
while n > 0:
display()
decrement()
countdown(10)
countdown(10)
but why can't i use the global n ? instead of nonlocal n. that gives me
UnboundLocalError: local variable 'n' referenced before assignment
this is the snippet
def countdown(start):
global n ##defined it global
n = start
def display():
print('--> %d' % n)
def decrement():
##no nonlocal varibale here
n -= 1
while n > 0:
display()
decrement()
countdown(10)

The global declaration doesn't automatically apply to nested functions. You need another declaration:
def decrement():
global n
n -= 1
so n in decrement also refers to the global variable.

You need to mark a variable as global in every function where you use it (or rather, every one where you assign to it). You marked n as global in countdown, but decrement still thinks it is local. If you want decrement to also use the global n, you need to put another global n inside decrement.

Related

How to create a recursive function, that generates multiple for loops and counts the total times

I tried to count the total number of calling times via a recursive function that generates n for-loops, but the variable seems to never change its value.
a=0
def recursivelooping(times,volumes):
if times==0:
a+=1
else:
for i in range(volumes):
return recursivelooping(times-1,i)
The result should look more like the variable a below, but instead I always got a zero.
def multiforloop(volumes):
a=0
for i in range(volumes):
for j in range(i):
for k in range(j):
a+=1
print(a)
If I understand correctly having a closure maybe the shortest solution:
def recursivelooping():
a = 0
def f(times, volumes):
nonlocal a
if volumes == 0:
return a
# Inner loop
for t in range(times):
for j in range(volumes):
a+=1
# Outer loop
return f(times, volumes-1)
return f
def multiforloop(times, volumes):
a=0
for i in range(volumes+1):
for t in range(times):
for j in range(i):
a+=1
return a
print(recursivelooping()(1, 10))
print(multiforloop(1, 10))
This will print 55 for both (as in n*(n+1)/2). A closure simply is a function (here f) accompanied by an environment (some context that maps names to variables, here a alone). That mean that a is accessible from within f as if it was a local variable, but it's not exactly a local variable it's a free variable
When you write a += 1 the normal behavior is to look for a local variable named a, instead here a is a free variable, that's why we need to add the nonlocal keyword to specify this.

closures with two inner functions python

I am trying to write a closure with two inner functions, but I am getting the below error
def factory(n=0):
#n=0
def current():
return n
return current
def counter():
n=n+1
return n
return counter
f_current,f_counter = int(input())
print(f_counter())
print(f_current())
I have the below error:
>>4
Traceback (most recent call last):
File "C:/Users/lokesh/Desktop/python/closure3.py",
line 13, in <module>
f_current,f_counter = int(input())
TypeError: 'int' object is not iterable
My requirement is after giving input 4,it should display:
4
5
I am new to python, can somebody help me here... thanks in advance
That looks more like what you want:
def factory(n=0):
def current():
return n
def counter():
nonlocal n
n += 1
return n
return current, counter
f_current, f_counter = factory()
print(f_current())
print(f_counter())
print(f_current())
print(f_counter())
Output:
0
1
1
2
With 4 as input:
f_current, f_counter = factory(4)
print(f_current())
print(f_counter())
4
5
factory() returns both inner functions. You need to use nonlocal to increment the n form the enclosing function. Without nonlocal you would not be able to modify n but would get:
UnboundLocalError: local variable 'n' referenced before assignment
because n is just a local variable. nonlocal n makes n from the enclosing function modifiable inside the inner function. Assessing n in current is fine, because Python's scoping rules allow read access to variables form an outer scope, here from the scope of the enclosing function.
Hi Mike ,I think non-local does'nt make any sense,I am giving the
solution which worked in my case.
def factory(n):
def current():
return n
def counter():
n=int(current())
n=n+1
return n
return current, counter
n=0
f_current, f_counter = factory((input()))
print(f_current())
print(f_counter())
def factory(n=0):
def current():
return n
def counter():
return n+1
return current, counter
f_current, f_counter = factory(int(input()))
print(f_current())
print(f_counter())
Mike's Nonlocal usage is very nice,but we can also access the variable value of n from enclosing scope by a new variable m inside Counter inner function and return it after incrementing.In that way,Nonlocal is not needed.
def factory(n=0):
def current():
return n
def counter():
m=n
m=m+1
return m
return current,counter
f_current,f_counter=factory(int(input()))
print(f_current())
print(f_counter())
`
You can simply use a new variable as the argument for the inner function which is equal to that of the outer function and proceed.
def factory(n=0):
def current():
return n
def counter(x=n):
return x+1
return current, counter
f_current,f_counter =factory(int(input()))
print(f_current())
print(f_counter())

Python Global Variables for Recursive Function

In my math class, we have been told to write a program in python. In one of the parts, I want to test the convergence of a series. While writing the program, I realized I was fundamentally misunderstanding something about how python handles global variables. Take this code:
def main():
global n
n = 1
def check():
a = 10
if n > a: print(n)
else: n += 1
check()
main()
This code fails because it says that n has not been defined yet. However, I can't define n inside of the check() function since that would just reset n to one upon every iteration! Is there some workaround for this problem?
As already stated in the comments, n isn't in the global scope yet, since it's inside the nested function check. You will need to add global n to the check's scope, to access the global n value from the nested function:
def main():
global n
n = 1
def check():
global n
a = 10
if n > a: print(n)
else: n += 1
check()
main()
#PedrovonHertwig also pointed out you don't need global n in main (which is the case in your current context, ignore this if you want to use n elsewhere in the top-level scope) and thatn is perfectly fine staying in main's local scope. You can then replace the global keyword inside check to nonlocal n, telling python to use the n that is not in the local scope nor the global scope, but main's scope.

unboundlocalerror local variable 'i' referenced before assignment

I'm new in python trying to execute this code:
def dubleIncrement():
j = j+2
def increment():
i = i+1
dubleIncrement()
if __name__ == "__main__":
i = 0
j = 0
increment()
print i
print j
But getting this error :
unboundlocalerror local variable 'i' referenced before assignment
Anybody has any idea why i is not global
Declare global keyword inside your functions to access the global as opposed to local variable. i.e.
def dubleIncrement():
global j
j = j+2
def increment():
global i
i = i+1
Note that when you declare i = 0 and j = 0 in your if statement, this is setting a global variable, but since it is outside the scope of any functions, the global keyword is not necessary to use here.
Ideally, you should try to stay away from using global variables as much as possible and try to pass variables as parameters to functions (think about what happens when you decide to use the variable names i and j again in some other function-- ugly collisions could occur!). The following would be one much safer way to write your code:
def dubleIncrement(x):
x = x+2
return x
def increment(x):
x = x+1
return x
if __name__ == "__main__":
i = 0
j = 0
i = increment(i)
j = dubleIncrement(j)
print i
print j

n+=1 returns 0 python function cannot change variable

n=0
def add(n):
print n
n+=1
print n
return n
whatever I do to "n" it is returned as 0. If I start n=0 and use add(n) I get n=0 back again. The "print n" after "n+=1" is "n=1". "return n" somehow transforms "n" back to "0" or does it have to do with a global "n=0" that I cannot change no matter what? I don't understand what is going on. How do I create a variable that can be changed in functions (from one function to another...).
n is a local variable in add(), and as such it is not the same variable as the global n. The two are (quite deliberately) not connected.
If you want to change the global, you have two options:
reassign the return value from add() back to the global n:
n = add(n)
alter the global directly by marking the name n in add as a global. Your add() function doesn't need to use an argument in that case:
def add():
global n
n += 1

Categories