Implementing a 'function-calling function' - function

I would like to write a bit of code that calls a function specified by a given argument. EG:
def caller(func):
return func()
However what I would also like to do is specify optional arguments to the 'caller' function so that 'caller' calls 'func' with the arguments specified (if any).
def caller(func, args):
# calls func with the arguments specified in args
Is there a simple, pythonic way to do this?

You can do this by using arbitrary argument lists and unpacking argument lists.
>>> def caller(func, *args, **kwargs):
... return func(*args, **kwargs)
...
>>> def hello(a, b, c):
... print a, b, c
...
>>> caller(hello, 1, b=5, c=7)
1 5 7
Not sure why you feel the need to do it, though.

This already exists as the apply function, though it is considered obsolete due to the new *args and **kwargs syntax.
>>> def foo(a,b,c): print a,b,c
>>> apply(foo, (1,2,3))
1 2 3
>>> apply(foo, (1,2), {'c':3}) # also accepts keyword args
However, the * and ** syntax is generally a better solution. The above is equivalent to:
>>> foo(*(1,2), **{'c':3})

Related

Problems with quad when using lambdify

I'm trying to solve these two integrals, I want to use a numerical approach because C_i will eventually become more complicated and I want to use it for all cases. Currently, C_i is just a constant so _quad is not able to solve it. I'm assuming because it is a Heaviside function and it is having trouble finding the a,b. Please correct me if I'm approaching this wrongly.
Equation 33
In [1]: import numpy as np
...: import scipy as sp
...: import sympy as smp
...: from sympy import DiracDelta
...: from sympy import Heaviside
In [2]: C_i = smp.Function('C_i')
In [3]: t, t0, x, v = smp.symbols('t, t0, x, v', positive=True)
In [4]: tot_l = 10
In [5]: C_fm = (1/tot_l)*v*smp.Integral(C_i(t0), (t0, (-x/v)+t, t))
In [6]: C_fm.doit()
Out[6]:
0.1*v*Integral(C_i(t0), (t0, t - x/v, t))
In [7]: C_fm.doit().simplify()
Out[7]:
0.1*v*Integral(C_i(t0), (t0, t - x/v, t))
In [8]: C_fms = C_fm.doit().simplify()
In [9]: t_arr = np.arange(0,1000,1)
In [10]: f_mean = smp.lambdify((x, v, t), C_fms, ['scipy', {'C_i': lambda e: 0.8}])
In [11]: try2 = f_mean(10, 0.1, t_arr)
Traceback (most recent call last):
File "/var/folders/rd/wzfh_5h110l121rmlxn61v440000gn/T/ipykernel_3164/3786931540.py", line 1, in <module>
try2 = f_mean(10, 0.1, t_arr)
File "<lambdifygenerated-1>", line 2, in _lambdifygenerated
return 0.1*v*quad(lambda t0: C_i(t0), t - x/v, t)[0]
File "/opt/anaconda3/lib/python3.9/site-packages/scipy/integrate/quadpack.py", line 348, in quad
flip, a, b = b < a, min(a, b), max(a, b)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Equation 34
In [12]: C_i = smp.Function('C_i')
In [13]: t, tao, x, v = smp.symbols('t, tao, x, v', positive=True)
In [14]: I2 = v*smp.Integral((C_i(t-tao))**2, (tao, 0, t))
In [15]: I2.doit()
Out[15]:
v*Integral(C_i(t - tao)**2, (tao, 0, t))
In [16]: I2.doit().simplify()
Out[16]:
v*Integral(C_i(t - tao)**2, (tao, 0, t))
In [17]: I2_s = I2.doit().simplify()
In [18]: tao_arr = np.arange(0,1000,1)
In [19]: I2_sf = smp.lambdify((v, tao), I2_s, ['scipy', {'C_i': lambda e: 0.8}])
In [20]: try2 = I2_sf(0.1, tao_arr)
Traceback (most recent call last):
File "/var/folders/rd/wzfh_5h110l121rmlxn61v440000gn/T/ipykernel_3164/4262383171.py", line 1, in <module>
try2 = I2_sf(0.1, tao_arr)
File "<lambdifygenerated-2>", line 2, in _lambdifygenerated
return v*quad(lambda tao: C_i(t - tao)**2, 0, t)[0]
File "/opt/anaconda3/lib/python3.9/site-packages/scipy/integrate/quadpack.py", line 351, in quad
retval = _quad(func, a, b, args, full_output, epsabs, epsrel, limit,
File "/opt/anaconda3/lib/python3.9/site-packages/scipy/integrate/quadpack.py", line 463, in _quad
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
File "/opt/anaconda3/lib/python3.9/site-packages/sympy/core/expr.py", line 345, in __float__
raise TypeError("Cannot convert expression to float")
TypeError: Cannot convert expression to float
So you are passing an unevaluated Integrate to lambdify, which in turn translates it call to scipy.integrate.quad.
Looks like the integrals can't be evaluated even with doit and simplify calls. Have you actually looked at C_fms and I2_s? That's one of the first things I'd do when running this code!
I've never looked at this approach. I have seen people lambdify the objective expression, and then try to use that in quad directly.
quad has specific requirements (check the docs!). The objective function must return a single number, and the bounds must also be numbers.
In the first error, you are passing array t_arr as the t bound, and it got the usual ambiguity error when checking where it is bigger than the other bound, 0. That's that b < a test. quad cannot use arrays as bounds.
I not sure why the second case gets avoids this problem - bounds must be coming from somewhere else. But the error comes when quad calls the objective function, and expects a float return. Instead the function returns a sympy expression which sympy can't convert to float. My guess there's some variable in the expression that's still a sympy.symbol.
In diagnosing lambdify problems, it's a good idea to look at the generated code. One way is with help on the function, help(I2_sf). But with that you need to be able to read and understand python, including any numpy and scipy functions. That's not always easy.
Have you tried to use sympy's own numeric integrator? Trying to combine sympy and numpy/scipy often has problems.

Calling Private Methods Recursively

I am writing a code that has a class Fraction with attributes Numerator and Denominator. The Output should display the fraction in a simplified form. For e.g. 20/100 should be display as 1/5.
I have tried the below code but getting a Type Error as below:
TypeError: unsupported operand type(s) for /: 'int' and 'NoneType'
class fraction:
def get_data(self):
self.__num=int(input("Enter the Nr:"))
self.__deno=int(input("Enter the Dr:"))
if (self.__deno==0):
print("Fraction not possible")
exit()
def display_data(self):
self.__simplify()
print(self.__num,"/",self.__deno)
def __simplify(self):
print("The simplified fraction is")
common_divisor=self.__GCD(self.__num,self.__deno)
self.__num=(self.__num)/(common_divisor)
self.__deno=(self.__deno)/(common_divisor)
def __GCD(self,a,b):
if (b==0):
return a
else:
self.__GCD(b,a%b)
f=fraction()
f.get_data()
f.display_data()
I have no clue how to solve this Error. Please help me as i am new to Python and want to build strong basics.
The problem is in this function definition:
def __GCD(self,a,b):
if (b==0):
return a
else:
self.__GCD(b,a%b)
There's no return statement on the else clause. (Also, the else clause can be implicit instead of explicit.) Instead try:
def __GCD(self, a, b):
if b == 0:
return a
return self.__GCD(b, a % b)

How can I print the function head, including name, arguments, and docstring?

Say I have the following:
def foo(arg1, arg2, arg3 = default, *args, *kwargs*):
"""This function is really cool."""
return
How can I define a new function functionprinter(f) so that functionprinter(f) would print
foo(arg1, arg2, arg3 = default, *args, *kwargs*)
This function is really cool.
or something of that nature? I already know foo.__name__ and foo.__doc__ and have seen the inspect module, specifically here: Getting method parameter names in python but can't seem to string together everything, in particular having the default arguments print properly. I am using Python 3.4.1.
Yup! You can with the inspect module:
import inspect
def foo(arg1, arg2, arg3=None , *args, **kwargs):
"""This function is really cool."""
return
def functionprinter(f):
print("{}{}".format(f.__name__, inspect.signature(f)))
print(inspect.getdoc(f))
functionprinter(foo)
Prints:
foo(arg1, arg2, arg3=None, *args, **kwargs)
This function is really cool.
Note that I changed your default argument to None just for this demonstration because I didn't have the variable default defined.
You can use inspect.signature (to represents the call signature of a callable object and its return annotation.) and inspect.getdoc :
>>> print(inspect.signature(foo))
(arg1, arg2, arg3=3, *args, **kwargs)
>>> inspect.getdoc(foo)
'This function is really cool.'
>>> print ('\n'.join((foo.__name__+str(inspect.signature(foo)),inspect.getdoc(foo))))
foo(arg1, arg2, arg3='', *args, **kwargs)
This function is really cool.

python a function in another function?

I have the following function:
def second(first, a):
# i want to return the results of first(a) in this function.
I just can't figure out how i can put values in (first(a)) without creating another function, or using lambda or any other modules? Any help is appreciated.
Maybe you could call the function first passing as parameter a, and then return the value it returned:
def second(first, a):
return first(a)
>>> def first(a, *args, **kwargs):
... print((a, args, kwargs))
...
>>> def second(func, a, *args, **kwargs):
... return func(a, *args, **kwargs)
...
>>> second(first, 'hello', 'world', do='something')
('hello', ('world',), {'do': 'something'})
>>> second(int, 15)
15
>>> second(range, 2, 5)
range(2, 5)
You can omit *args or **kwargs part if you know you don't need additional arguments or keyword arguments for your functions.

name for a function that transforms assignment statements to expressions

update
Since one effect of these functions is to provide a way to use method chaining on methods that would not normally support it *, I'm considering calling them chain and copychain, respectively. This seems less than ideal though, since the would-be copychain is arguably a more fundamental concept, at least in terms of functional programming.
original
I'm calling it a boxer for now. The code is in Python, though the question is general:
def boxer(f):
"""Return a function g(o, *args, **keyargs) -> o
`g` calls `f` on `o` with the remaining arguments
and returns `o`.
>>> l = [2]
>>> def increment_list_element(l, i):
... l[0] += i
>>> adder = boxer(increment_list_element)
>>> adder(l, 2)
[4]
>>> def multiply_list_element(l, i):
... l[0] *= i
>>> multiplier = boxer(multiply_list_element)
>>> sum(multiplier(l, 6))
24
"""
def box(o, *args, **keyargs):
f(o, *args, **keyargs)
return o
return box
A similar concept copies the would-be assignee, and assigns to and returns the copy. This one is a "shadow_boxer":
from copy import deepcopy
def shadow_boxer(f):
"""Return a function g(o, *args, **keyargs) -> p
`g` deepcopies `o` as `p`,
executes `f` on `p` with the remaining arguments,
and returns `p`.
>>> l = [2]
>>> def increment_list_element(l, i):
... l[0] += i
>>> adder = shadow_boxer(increment_list_element)
>>> adder(l, 2)
[4]
>>> def multiply_list_element(l, i):
... l[0] *= i
>>> multiplier = shadow_boxer(multiply_list_element)
>>> sum(multiplier(l, 6))
12
"""
def shadow_box(o, *args, **keyargs):
p = deepcopy(o)
f(p, *args, **keyargs)
return p
return shadow_box
In addition, I'd like to find out about resources for learning more about these sorts of things — though I'm similarly unsure of a name for "these sorts of things". It does seem related to functional programming, although as I understand it, these technique would be unnecessary in a true functional language.
This is pretty much the same thing as Ruby's Object#tap. Don't know how you feel about the name, but that's what they call it.
What the boxer function returns is probably defined closure in some programming languages. If there is not already a function with this name, I would call the function closure.