Closures: ========= what is closure? ================ ==> a nested function Syntax: def outer_function(): implementation def inner_function(): implementation ==> has access a variable from an enclosing function that has finished its execution. ==> That variable not bound in the local scope. ==> If the variable is immutable type: we can use "nonlocal" keyword to modify that immutable variable. Advantage: ========== 1) can avoid the usage of global variable 2) provide some form of the data hiding. Nested Function: ================ def fun1(): # Outer function print("This is the Outer function") def fun2(): # Inner Function print("This is the Inner function") print("Hi") print("Good Morning") print("This is Python Advanced Class") fun2() fun1() ========================================== Variable Scope: =============== def outerFunction(x): # x = 1122 y = 1221 def innerFunction(z): # z = 1234 return x + y + z return innerFunction returningFunction = outerFunction(1122) # function aliasing returningFunction = innerFunction result = returningFunction(1234) print(result) ================================= def outer(name): # name = local valriable to the "outer" function name = "Ashok IT" def inner(): print("Name = ",name) return inner res1 = outer("Python") # function aliasing res1() ======================================================= Non-local: ========= def f1(): a = 112 # Immutable def f2(): nonlocal a b = 121 a = a + b return a return f2 r1 = f1() print(r1()) print(r1()) print(r1()) print(r1())