I have a function
def x(whatever):
....
I want to assign
y = x(whatever)
So that I can pass around y to a wrapper which then calls the method that y refers to. The problem is that each type of function x can have variable arguments. Is it possible to do this in python, assigning y = x(whatever) and then pass around y as a parameter.
I tried y = x(whatever) and passed around y to the wrapper which then did
ret = y() # dict object is not callable
Thanks!
I think you are looking for functools.partial():
from functools import partial
y = partial(x, whatever)
When y is called, x(whatever) is called.
You can achieve the same with a lambda:
y = lambda: x(whatever)
but a partial() accepts additional arguments, which will be passed on to the wrapped callable.
Related
I'm currently learning about closure and this code was presented:
def outer_func(x):
y = 4
def inner_func(z):
print(f"x = {x}, y = {y}, z = {z}")
return x + y + z
return inner_func
for i in range(3):
closure = outer_func(i)
print(f"closure({i+5}) = {closure(i+5)}")
I understand x is defined at the point outer_func is assigned to closure, and y is defined within the function each time. My question is how is z defined? Shouldn't the call to closure overwrite the value of x? How does python know to assign this new value to z?
My question is how is z defined?
z is a parameter of inner_func. It means it's always local to the inner_func function(local variable). When the outer_func function is called the body of it will be executed, which indeed first create inner_func and give you back a reference to it. Then whatever you pass to inner_func, it uses as the z. It's a normal argument passing.
Shouldn't the call to closure overwrite the value of x?
inner_func is your closure. It has access to it's enclosing scope which is outer_func. x is a parameter of outer_func, it gets it's value from executing the line:
closure = outer_func(i)
So whatever you pass to outer_func becomes available to the inner_func's body. (Closure mechanism)
How does python know to assign this new value to z?
I already answered this in the first part. In the line:
print(f"closure({i+5}) = {closure(i+5)}")
you are passing the value of z in closure(i+5) part.
Q: Now where does inner_func get y's value from? A: Again it's a closure, it has access to outer_func namespace. y is always defined when outer_func() is called. Nothing can change it's value in your code. That loop can only change x because it comes from outside. (argument)
Your question is:
I understand x is defined at the point outer_func is assigned to closure, and y is defined within the function each time. My question is how is z defined? Shouldn't the call to closure overwrite the value of x? How does python know to assign this new value to z?
Your code is:
def outer_func(x):
y = 4
def inner_func(z):
print(f"x = {x}, y = {y}, z = {z}")
return x + y + z
return inner_func
for i in range(3):
closure = outer_func(i)
print(f"closure({i+5}) = {closure(i+5)}")
The call to closure is effectively a call to inner_func (not outer_func) and the argument passed to closure will be assigned to z (not x).
Explanation:
Each execution of closure = outer_func(i) does the following:
call outer_func() thereby effectively assigning the passed argument i to the variable x in the scope of outer_func()
execute y = 4
leave outer_func() with a return value of type function whose value is inner_func
assign the return value of outer_func() (namely the function inner_func) to closure, with ongoing access to the variables in the containing scope of inner_func() (namely, the scope of outer_func()).
Each call to closure() within the for loop does the following:
call inner_func() thereby assigning the passed argument to z in the scope of inner_func()
execute the body of inner_func() where x and y have the values they had at the time of the call to outer_func() that created this copy of inner_func as a closure.
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.
I have very basic question. For some reason I'm not able to recall how to do it. How to access the variables defined in the function which is not declared in class. How to access y variable ? And how to pass the value for lambda ? And how to get back the value of c defined inside lambda ?
def fun ():
y = 100
x = lambda c,s,y : c*s*y
Also how to pass the values to lambda from function ?
If you want to use y in lambda then don't specify it as an argument for the lambda:
def fun():
y = 5
x = lambda c, s: c*s*y
return x(2, 3)
>>> fun()
30
I create a function which returns an value specified by an variable. Like
y = 1.
def f(x):
return y
I need this function as an function object to create another object
dist = dist.distribution(f, other_variables)
this works fine. But if i want to create several different distribution objects (with different functions f in the sense that y changes) Like
dist = dist.distribution(f, other_variables)
y = 2.
dist2 = dist.distribution(f, other_variables)
Then all distribution objects only return the last specified value y. I.e.
dist.f()(1.)
>>>> 2.
dist2.f()(1.)
>>>> 2.
Instead of the expected
dist.f()(1.)
>>>> 12.
dist2.f()(1.)
>>>> 2.
The problem clearly is, that the function f accesses the variable only when it is called and not one time initially.
Is there a way around it?
What I want at the end is:
A function with one variable only (x, although this doesnt do anything in this case, it is needed in others), which returns the value of y of the moment, when the distribution is created. So in principle I want that at the initialisation of the distribution, the given function is deepcopyed, in the sense, that it is no longer influenced by any change of variables.
Is this possible?
Don't use globals for this. There is no need to 'deepcopy' the function either; the y global is not part of the function state at all.
Use a function factory that provides a scoped value instead, or use a functools.partial() to provide a default argument to your function.
Function factory:
def produce_f(y):
def f(x):
return y
return f
dist = dist.distribution(produce_f(1.), other_variables)
Now y is a scoped value for f, produce_f() returns a new f every time it is called, and y is stored as a cell variable for f.
Demo:
>>> f1 = produce_f(12.)
>>> f2 = produce_f(42.)
>>> f1('foo')
12.0
>>> f2('foo')
42.0
Using functools.partial():
from functools import partial
def f(y, x):
return y
dist = dist.distribution(partial(f, 1.), other_variables)
Here partial(f, 1.) produces a new callable that will call f(1., ...) whenever called, appending any extra arguments passed in.
Demo:
>>> f1 = partial(f, 12.)
>>> f2 = partial(f, 42.)
>>> f1('foo')
12.0
>>> f2('foo')
42.0
Let's say I have a function
def x():
print(20)
Now I want to assign the function to a variable called y, so that if I use the y it calls the function x again. if i simply do the assignment y = x(), it returns None.
You simply don't call the function.
>>> def x():
>>> print(20)
>>> y = x
>>> y()
20
The brackets tell Python that you are calling the function, so when you put them there, it calls the function and assigns y the value returned by x (which in this case is None).
When you assign a function to a variable you don't use the () but simply the name of the function.
In your case given def x(): ..., and variable silly_var you would do something like this:
silly_var = x
and then you can call the function either with
x()
or
silly_var()
when you perform y=x() you are actually assigning y to the result of calling the function object x and the function has a return value of None. Function calls in python are performed using (). To assign x to y so you can call y just like you would x you assign the function object x to y like y=x and call the function using y()
The syntax
def x():
print(20)
is basically the same as x = lambda: print(20) (there are some differences under the hood, but for most pratical purposes, the results the same).
The syntax
def y(t):
return t**2
is basically the same as y= lambda t: t**2. When you define a function, you're creating a variable that has the function as its value. In the first example, you're setting x to be the function lambda: print(20). So x now refers to that function. x() is not the function, it's the call of the function. In python, functions are simply a type of variable, and can generally be used like any other variable. For example:
def power_function(power):
return lambda x : x**power
power_function(3)(2)
This returns 8. power_function is a function that returns a function as output. When it's called on 3, it returns a function that cubes the input, so when that function is called on the input 2, it returns 8. You could do cube = power_function(3), and now cube(2) would return 8.
lambda should be useful for this case.
For example,
create function y=x+1
y=lambda x:x+1
call the function
y(1)
then return 2.
I don't know what is the value/usefulness of renaming a function and call it with the new name. But using a string as function name, e.g. obtained from the command line, has some value/usefulness:
import sys
fun = eval(sys.argv[1])
fun()
In the present case, fun = x.
def x():
print(20)
return 10
y = x
y()
print(y)
gives the output
20
<function x at 0x7fc548cd3040>
so it does not actually assign the value returned by x() to the variable y.