python pass multiple parameters to function that expects function - python-3.x

I am stuck on a problem and I would be grateful for help.
Consider the following example.
# can be changed
def inner(x):
x = 4
return x
# can not be changed
def outer(a, b):
b = b(b)
return a + b
# can be changed - I want to pass two parameters to inner
res = outer(
a = 3,
b = inner
)
print(res)
Now important to note is that I can not change the function outer(), because it comes from a common code base / package.
How can I pass multiple parameters to inner()? inner() can be changed as needed, but it needs to return the function, not the int since outer() expects a function.
Thank you in advance!
I tried passing multiple parameters, but outer() expects a function. This example illustrates the function ExternalTaskSensor of the python package airflow. The parameter
execution_date_fn
expects a function to be returned.

Related

How to bind parameters to a function without calling it

Let's say I have the following function:
def add(x, y):
return x+y
I would like to bind x=2 and y=2 to the function but not actually call it. What is the correct way to do this? I've done this sometimes with add_bound=lambda: add(2,3), but I'm wondering if this is the 'pythonic' approach or there is another way to do it (perhaps binding certain arguments, and then passing other arguments later.
Often this will be done with a decorator. Here is a general example:
add = lambda x,y: x+y
def wrap(outer_func, *outer_args, **outer_kwargs):
def inner_func(*inner_args, **inner_kwargs):
args = list(outer_args) + list(inner_args)
kwargs = {**outer_kwargs, **inner_kwargs}
return outer_func(*args, **kwargs)
return inner_func
In this case you can do things such as the following:
# pass both at once
>>> x=wrap(add,2,3)
>>> x()
5
# pass one at binding, second at call
>>> x=wrap(add,2)
>>> x(3)
5
# pass both when called
>>> x=wrap(add)
>>> x(2,3)
5
Note that the above is very similar to functools.partial:
The partial() is used for partial function application which “freezes” some portion of a function’s arguments and/or keywords resulting in a new object with a simplified signature. For example, partial() can be used to create a callable that behaves like the int() function where the base argument defaults to two:
from functools import partial
basetwo = partial(int, base=2)
basetwo.__doc__ = 'Convert base 2 string to an int.'
basetwo('10010')
18
def add(x=2, y=2):
return x+y

Is there a way to get give one variable to a function and retrieve a different variable back from the second function and use it in the first function

I am trying to use the output of one function in a second function then retrieving a variable from the second function to be used in the first function. The code below is a simplification of what I am trying to do
def function1():
x=15
return x
function2(y)
print(x+y)
def function2():
y=x-12
return y
function1()
I am not getting an actual value for y when I check by adding a print statement for x in function2. Is there a way to do this or do i need to make a 3rd function to handle this?
Pass variable x to function2, and store the return value from function2 in a local variable in function 1.
def function1():
x=15
y = function2(x)
print(x+y)
return x
def function2(x):
y=x-12
return y
function1()

Accommodating empy function parameter without default value

I'm writing a simple function in python 3.6 to find the distance between two points in n-dimensional space. I pass the coordinates as one-dimensional lists to my function. Here is what I have written:
def Distance(a: list[float], b: list[float]):
dimension = len(a)
sum = 0
for i in range(dimension):
sum += (b[i]-a[i])**2
return math.sqrt(sum)
This should work just fine if both a and b are passed explicitly. But I want to add additional functionality: if only a is passed, its distance from the origin will be calculated.
In C++, the language I am most familiar with, I would do this using function overloading. In that case, the two functions would simply have a different number of parameters. But this isn't an option for me in Python.
Any help with this would be greatly appreciated. Thank you in advance.
Edit:
The updated definition
def Distance(a: List[float], b=None):
if b:
arg = sum((x1 - x2)**2 for x1, x2 in zip(a,b))
else:
arg = sum(x**2 for x in a)
return math.sqrt(arg)
works for both cases.
An idiomatic definition could be
def distance(a, b=None):
from math import sqrt
d2=sum((x1-x2)**2 for x1,x2 in zip(a,b)) if b else sum(x**2 for x in a))
return sqrt(d2)
I confide that it's possible to use type hints as well, but I'm not an expert.
As a final remark, you used sum as a name, while it's recommended that you do not mask builtin names (I have used the sum builtin in my function definition)
The prototype must indeed be with None, so you have to change the function types because None is obviously not a list:
def Distance(a: list[float], b=None):
Then:
if not b:
b = [0.] * dimension

Problem with calling a variable from one function into another

I am trying to call a variable from one function into another by using the command return, without success. This is the example code I have:
def G():
x = 2
y = 3
g = x*y
return g
def H():
r = 2*G(g)
print(r)
return r
H()
When I run the code i receive the following error NameError: name 'g' is not defined
Thanks in advance!
Your function def G(): returns a variable. Therefore, when you call it, you assign a new variable for the returned variable.
Therefore you could use the following code:
def H():
G = G()
r = 2*G
print (r)
You don't need to give this statement:
return r
While you've accepted the answer above, I'd like to take the time to help you learn and clean up your code.
NameError: name 'g' is not defined
You're getting this error because g is a local variable of the function G()
Clean Version:
def multiple_two_numbers():
"""
Multiplies two numbers
Args:
none
Returns:
product : the result of multiplying two numbers
"""
x = 2
y = 3
product = x*y
return product
def main():
result = multiple_two_numbers()
answer = 2 * result
print(answer)
if __name__ == "__main__":
# execute only if run as a script
main()
Problems with your code:
Have clear variable and method names. g and G can be quiet confusing to the reader.
Your not using the if __name__ == "__main__":
Your return in H() unnecessary as well as the H() function.
Use docstrings to help make your code more readable.
Questions from the comments:
I have one question what if I had two or more variables in the first
function but I only want to call one of them
Your function can have as many variables as you want. If you want to return more than one variable you can use a dictionary(key,value) List, or Tuple. It all depends on your requirements.
Is it necessary to give different names, a and b, to the new
variables or can I use the same x and g?
Absolutely! Declaring another variable called x or y will cause the previous declaration to be overwritten. This could make it hard to debug and you and readers of your code will be frustrated.

Why does assigning lambdas not work as expected in Python 3.5?

I know Python is supposed to have first class functions, and I've written some Python which "confirms" that, but the following explodes (runs out of stack depth) my IDLE in 3.5:
k = lambda x:x+1
k = lambda x:k (x+1)
k(0)
Shouldn't it evaluate to 2?
k = lambda x:x+1
j = lambda x:k (x+1)
j(0)
certainly does.
Visualize with lambda
A little printing may help to understand what is going on:
k = lambda x: x+1
print('before:', id(k))
k = lambda x: print('in :', id(k))
k(0)
print('after :', id(k))
before: 4428659024
in : 4428658208
after : 4428658208
The id of the last lambda is the same as the one use inside it. This nicely demonstrates the late binding.
Translate into function statements
Things might a bit clearer if you translate the lambdas into function define with def:
def k(x):
return x + 1
def k(x):
return k(x+1)
k(0)
It is pretty clear that the first definition does make sense as it is overridden by the second one.
In addition, even you use different names for the functions and re-assign the function name:
def k(x):
return x + 1
def j(x):
return k(x+1)
k = j
it appears to be clearer that the first function definition doesn't make sense because the function can never be reached.
The name lookup of k is done at runtime, which means that the function calls itself an infinite number of times (and that the first line does nothing useful). If you want the result you expect then you will have to use the ternary operator to return immediately instead of recursing.

Resources