def raise_val(n):
"""Return the inner function."""
def inner(x):
"""Raise x to the power of n."""
raised = x ** n
return raised
return inner
square = raise_val(2)
cube = raise_val(3)
print(square(2), cube(4))
Outputs:
4 64
Can anybody explain to me how come square(2) knows that the argument passed is x?
this code uses the concept of lexical closures or closures.Closures are the function that remembers the parameters passed to their parent function.The more technical definition will be,Closures are the function that remembers values in enclosing scope even if they are not actually present in the memory.
#for example`
def outer(x):
def inner():
print(f"The argument passed to outer was {x}")
'''Notice how inner() will grab the argument passed to the outer function'''
return inner
value=outer(69)
print(value())
Maybe this will help: https://stackabuse.com/python-nested-functions/
Notice you "sends arguments twice" (not really): first in square = raise_val(2) and second in square(2). What happens? The first calls return a function: you call to raise_val and it returns inner, which is a function. Now square variable actually holds a function. Second call, square(2), just call to the function.
It's the same as:
def a(x):
print(x)
square = a
print(square(5))
In this example, square holds a function. It's the same as in your code, since raise_val returns a function. Square holds inner method, and later it is been called. You send x directly: square(2) sends 2 for x of course.
A more interesting can be "how inner remembers n?", and as others mentioned in comments: it's manages variables of current scope.
Related
def myfunc(n):
return lambda a : a * n
mydoubler = myfunc(2)
print(mydoubler(11))
The value of n = 2, after that I'm confused what is the value of a, and how the lambda function is executed.
Your myfunc is a nested function, lambdas are functions.
An equal implementation would be:
def outer(n):
def inner(a):
return a * n
return inner
Which returns a function like your original myfunc as well. Since the return of the call of myfunc is also a function, you may well call the inner function as well.
When the outer function is called, the inner lambda creates a function. The outer lambda then returns the called function.It happens that describe above..i.e: when we call mydoubler(11),given the value a=11 and call n=2.
Python
Can anyone help me to understand this code, I am new to Python, how does this function work?
def makeInc(x):
def inc(y):
return y + x
return inc
incOne = makeInc(1)
incFive = makeInc(5)
print(incOne(5)) # returns 6
print(incFive(5)) # returns 10
Higher-order functions
Functions like makeInc that in turn, return another function are called higher order functions. Usually, functions are known to accept data as input and return data as output. With higher order functions, functions instead of data, either return code as output or accept code as input. This code is wrapped into a function. In Python, functions are first class citizens which means functions, just like data, can be passed around. For instance:
myvariable = print
Notice, how I have assigned print to myvariable and how I have dropped the parentheses after print Functions without parentheses are called function objects. This means myvariable now is just another name for print:
print("Hello World!")
myvariable("Hello World!")
Both of the above statements do the exact same thing. What can be assigned to variables can also be returned from functions:
def myfunction():
return print
myfunction()("Hello World!");
Now let's look at your example:
def makeInc(x):
def inc(y):
return y + x
return inc
makeInc is a function that accepts a parameter called x. It then defines another nested inner function called inc which takes in a parameter called y. The thing about nested functions is that they have access to the variables of the enclosing function as well. Here, inc is the inner function but it has access to x which is a variable of the enclosing outer scope.
The last statement return inc returns the inner function to the caller of makeInc. What makeInc essentially is doing, is creating a custom function based on the parameter it receives.
For instance:
x = makeInc(10)
makeInc will first accept 10 and then return a function that takes in an argument y and it increments y by 10.
Here, x is a function that takes in any argument y and then increments it by 10:
x(42) # Returns 52
nonlocal
However, there is a caveat when using nested functions:
def outer():
x = 10
def inner():
x = 20
inner()
print(x) # prints 10
Here, you would assume that the last print statement will print 20. But no! When you assign x = 20 in the inner function, it creates a new local variable called x which is initialized to 20. The outer x remains untouched. To modify the outer x, use the nonlocal keyword:
def outer():
x = 10
def inner():
nonlocal x = 20
inner()
print(x) # prints 20
If you are directly reading x inside inner() instead of assigning to it, you do not need nonlocal.
What is happening here is that makeInc() returns a function handle pointing to specific implementation of inc(). So, calling makeInc(5) "replaces" the x in inc(y) to 5 and returns the callable handle of that function. This handle is saved in incFive. You can now call the function as defined (inc(y)). Since you set x=5 before, the result will be y+5.
Here is a sample decorator:
def smart_divide(func):
def inner(a,b):
print("I am going to divide",a,"and",b)
if b == 0:
print("Whoops! cannot divide")
return
return func(a,b)
return inner
#smart_divide
def divide(a,b):
return a/b
If func is an object then how do the variables a and b get accessed from it?
Isn't it like trying to to do this?
def func(potato):
print(y, x)
Is there a fundamental concept I am not getting? Is what is happening here part of some pattern in Python or is it a special case situation where a and b know were to look because it is a generator?
Update
New example from another stack exchange answer
def my_shiny_new_decorator(a_function_to_decorate):
def the_wrapper_around_the_original_function():
print("Before the function runs")
a_function_to_decorate()
print("After the function runs")
return the_wrapper_around_the_original_function
def a_stand_alone_function():
print("I am a stand alone function, don't you dare modify me")
Generators the manual way
a_stand_alone_function = my_shiny_new_decorator(a_stand_alone_function)
a_stand_alone_function()
Generators the proper way
#my_shiny_new_decorator
def another_stand_alone_function():
print("Leave me alone")
According to the place where I got the new answer from the 'manual' way and the 'proper way' are the same .
I think this example may have caused me to get stuck as I was trying to extend it to when there were parameters involved.
I now realise that what I was imagining didn't make sense
I thought that the original code I posted was equivalent to this
divide = smart_divide(divide(a,b))
which if executed would look like this
def smart_divide(divide(a,b)):
def inner(a,b):
print("I am going to divide",a,"and",b)
if b == 0:
print("Whoops! cannot divide")
return
return func(a,b)
return inner
But this would cause divide(a,b) to be executed right in the top line
in the new example 'a_stand_alone_function' did not have () on the end. Which means it was treated as an object.
So my idea of it looking like this def smart_divide(divide(a,b)): doesn't make sense because the function won't be treated as an object anymore
This leaves me confused as to how smart_devide get the information passed as a parameter.
smart_divide doesn't get a and b passed into it. It returns a function object (the inner function), and that function gets a and b passed into it.
You can see what's actually happening if you try this:
def smart_divide(func):
print("I am running in smart_divide; func=", func)
def inner(a,b):
print("I am going to divide",a,"and",b)
if b == 0:
print("Whoops! cannot divide")
return
return func(a,b)
print("I am returning from smart_divide")
return inner
print("I am running at top level before declaring divide")
#smart_divide
def divide(a,b):
return a/b
print("The name 'divide' now refers to", divide)
print("I am now going to call the divide function")
divide(1, 2)
This outputs:
I am running at top level before declaring divide
I am running in smart_divide; func= <function divide at 0x108ff2bf8>
I am returning from smart_divide
the name 'divide' now refers to <function smart_divide.<locals>.inner at 0x10565db70>
I am now going to call the divide function
I am going to divide 1 and 2
No, your decorator returns inner as new implementaion for divide. Thus, you first call the function inner when your program executes divide(1, 2) for instance. Calls to divide have always to respect the signature of inner (and divide as in your code).
A function like
def divide(a, b): # signature
return a / b # implementation or body
consists of two parts. The signature describes the parameters, and the implementation what the function does.
Your decorator will only modify the implementation of your function as follows:
def divide(a, b): # signature remains unmodified
print("I am going to divide",a,"and",b) # implementation of inner
if b == 0:
print("Whoops! cannot divide")
return
return a / b # call to the original implementation of divide
The name and the signature of divide remains the same. Thus, the signature of inner matters, and not the signature of your decorator.
I read an example on closure
def outer():
x = 1
def inner():
print x # 1
return inner
The life of our variable x is only till the time the function outer runs .
When i call outer and it returns the adress of inner , the variable x should have died because the function outer has exited but still how can i acess it through the returned inner function ?
python variable scope in nested functions
This link answered that the value of variables used by inner is stored when outer returns inner function to caller , but
Now see this code
def outer():
x = 1
def inner():
print x*n # n not defined anywhere
return inner
I ran this code and
This piece of code doesn't give any error when i call outer , that means that python doesn't checks the variables used by inner function while running outer . so how does it know it has to retain 'x' , after exiting ?
The life of our variable x is only till the time the function outer runs
No. x lives as long as it's reachable from somewhere. And, it is — from the inner function.
This piece of code doesn't give any error when i call outer , that means that python doesn't checks the variables used by inner function while running outer
n could be defined after calling outer, but before calling its result, inner. In that case inner's body if perfectly legitimate.
If you didn't return inner, then there'd be no reason to keep x, because you can't reach inner, thus can't somehow involve x into computation.
The way x is remembered is because python has a special __closure__ attribute that remembers the object from the enclosing scope that the local function needs and keeps a reference to it so it can be used in the local function:
def outer():
x = 1
def inner():
print(x)
return inner
o = outer()
print(o.__closure__)
(<cell at 0x7fa18a2fc588: int object at 0x9f8800>,)
If you assign o = outer() and then call o() you are then calling the inner function and you will get an error, calling outer() does not call the inner function.
If you were to declare a function f and put a print(n) in the body then unless you actually call f you won't get an error so the same logic applies to your inner function, you are not actually calling it with outer() so you don't get an error:
def f():
print(n) # will only error when we actually call `f()`
If calling the inner function happened when you called outer it would defeat the purpose, consider the following function factory where we take in an exponent e to raise i to:
def raise_exp(e):
def power(i):
return i ** e # n not defined anywhere
return power
sq = raise_exp(2) # set exponent but does not call power
print(sq(2)) # now we actually all power
cube = raise_exp(3)
print(cube(3))
25
27
i have homework and we need to do something like iterator, the func work great but the techer told he run the func with (t=Make_iterator()) like this, what i do wrong? tnx!
global x
x=-1
def Make_iterator(fn):
global x
x+=1
return fn(x)
fn=lambda y:y*2
t=Make_iterator(fn)
print(t())
I think you want a closure, which is a function defined within the local namespace of anther function, so that it can access the outer function's variables:
def make_iterator(func):
x = -1
def helper():
nonlocal x
x += 1
return func(x)
return helper
The nonlocal statement allows the inner function to modify the variable declared in the outer function (otherwise you'd either get an error, or you'd bind your own local variable without changing the outer one). It was only added in Python 3, so if you're still using Python 2, you'll need to wrap the x value in a mutable data structure, like a list.
Another approach to the same idea is to write class, rather than a function. An instance of a class can be callable (just like a function) if the class defines a __call__ method:
class MyIterator(object):
def __init__(self, func):
self.index = -1
self.func = func
def __call__(self):
self.index += 1
return self.func(self.index)
This can be useful if the state you need to keep track of is more complicated (or should change in more complicated ways) than the simple integer index used in this example. It also works in Python 2 without annoying workarounds.
I think he wants your Make_iterator function to return a function that acts as an iterator. So you could wrap the contents of your current Make_iterator function within an inner function f and return that:
def Make_iterator(fn):
def f():
global x
x+=1
return fn(x)
return f
Now if you do t = Make_iterator(fn), every time you call t() it will return the next value of the iterator, in your case 0, 2, 4, 6, 8, etc...