Python - notation for redundant lambda parameters - python

I am trying to build a function
f(x, y, z)
where neither x nor y have any impact on the result. Nonetheless, they must be passed to the function, as the passing is done by a library. I would like to:
solve this using a lambda expression, and
ensure that anyone reading my code will immediately know that x and y are redundant.
As I have gathered, using the underscore character for redundant return values from multiple-value-returning functions is common practice, e.g.
a, _, c, d, _, _ = return_six_things(),
however, trying
f = lambda _, _, z: some_operation(z)
crashes with the exception warning the author about using 'duplicate arguments' (two underscore characters).
Are there any other options?
P.S. to avoid the XY problem, the reason I want to use lambdas is to save a few source code characters. I would love to use them anyway, but declaring that "these parameters will not be used" is more important for me.

I'd use a double underscore (__) for the second unused argument:
f = lambda _, __, z: some_operation(z)

Options:
# pass in z as a keyward argument
# like this: f(x,y,z=1)
f = lambda *_,z: some_operation(z)
#Or:
# pass in any number of arguments and only use the last argument
f = lambda *z: some_operation(z[-1])

Related

Getting error saying the truth value of an array with more than one element is ambiguous

...and a suggestion to Use a.any() or a.all().
I am new to python and i am trying to implement a sabr model. I have defined a function with the following parameters:
def haganimpliedvol(a,f,k,B,v,t,p):
if k != f:
z = v/a*math.pow(f*k,(1-B)/2)*math.log(f/k)
xz = math.log((math.sqrt(1-2*p*z+math.pow(z,2))+z-p)/(1-p))
sigma = a/math.pow(f*k,(1-B)/2)*(1 + math.pow(1-B,2)/24* math.pow(math.log(f/k),2)+\
math.pow(1-B,4)/1920* math.pow(math.log(f/k),4))*\
xz*\
(1+(math.pow(1-B,2)/24*math.pow(a,2)/math.pow(f/k,1-B)+1/4*(p*B*v*a)/math.pow(f/k,(1-B)/2)+\
(2-3*math.pow(p,2))/24*math.pow(v,2)))*t
else:
sigma = a/math.pow(f,1-B)*\
(1+(math.pow(1-B,2)/24*math.pow(a,2)/math.pow(f,(2-2*B))+\
1/4*(p*B*a*v)/math.pow(f,1-B)+(2-3*math.pow(p,2))/24*math.pow(v,2)))*t
return(sigma)
Now I define another function to and call the haganimpliedvol() function
params = [0.4,0.6,0.1,-0.4]
def objective(params):
global k,sigma_iv,t,f
a = params[0]
B = params[1]
v = params[2]
p = params[1]
for (i,j,k) in zip(k,t,f):
calc_vols = np.array([haganimpliedvol(a,f,k,B,v,t,p)])
return(calc_vols)
As can be seen, a few parameters in the functions are list. I want to get an array as an output. However, I keep getting the message in the subject line.
Pay attention to the variables in this call:
for (i,j,k) in zip(k,t,f):
calc_vols = np.array([haganimpliedvol(a,f,k,B,v,t,p)])
for the zip to work, k,t, f have to be lists or arrays of matching size;
Done use k for an iteration variable; it is already used in the zip. I think you are just being careless here; or confused.
And the arguments to the hagen... function. Are the f, k, t supposed to be variables used in the zip? It would make more sense to use the iteration variables (i,j,?). Again, this just looks like you are careless, or don't care what happens.
As for the ambiguity error, that most likely arises in the
if k != f:
If either k or f is an array (or both) the k!=f will be a boolean array. That can't be used in if, which requires a simple True or False value. It does not iterate on the conditions. It is a basic Python if - a switch.
This ambiguity error comes up frequently, in various contexts, but all with the same basic issue - using an array in a context that requires a scalar T/F. A simple web search should provide lots of examples.
#hpaulj thank you for leading me on the right path. I vectorized my function and made some edits and now it is working fine.
haganimpliedvol = np.vectorize(haganimpliedvol,excluded = ['a','B','v','p'])
params = [0.2,0.7,0.01,-0.4]
def objective(params):
global k,sigma_iv,t,f
a = params[0]
B = params[1]
v = params[2]
p = params[1]
calc_vols = haganimpliedvol(a,f,k,B,v,t,p)
return(calc_vols)
Are you sure you want to pass arrays into the haganimpliedvol() function?
The general convention is to write functions which take a single input type.
Maybe call it one per item in the array?
Or write the function in a way that, if it sees the input is a list it iterates and if it sees the inputs arent lists then it just calculates it one time.
See this thread for ideas
How to make a function that can handle single inputs or lists of inputs

unable to understand lambda map function

Seeking guidance to understand a lambda-map function. In the below, I see that the file "feedback" is read line by line and stored in a list "feedback". I'm unable to get my head around the variable x. I don't see the variable "x" declared anywhere. Can someone help me understand the statement?Thanks in advance
f = open('feedback.txt','r')
feedback = list(map(lambda x:x[:-1],f.readlines())
f.close()
The map function will execute the given function for every element in the list.
In your code the map function will get lambda x:x[:-1].
You can read that like: for every x in f.readlines() return everything except the last element of x.
So x will be every line the file. lambda x: you could see as def thing(x):.
I replaced lambda with a standard func:
def read_last(x): #x means a line
return x[:-1]
f = open('feedback.txt','r')
feedback = list(map(read_last, f.readlines())
f.close()
Maybe it will help.
lambda function is a simple anonymous function that takes any number of arguments, but has only one expression.
lambda arguments : expression
It is anonymous because we have not assigned it to an object, and thus it has no name.
example f and g are somewhat same:
def f(x):
# take a string and return all but last value
return x[:-1]
g = lambda x: x[:-1]
so:
f('hello') == g('hello') #True ->'hell'
But g is not how we would use lambda. The whole aim is to avoid assigning ;)
Now map takes in a function and applies it to an iteratable:it returns a generator in Python 3+ and thus a list is used to case that generator to a list
data = ['we are 101','you are 102','they are 103']
print(list(map(lambda x:x[:-1],data)))
#->['we are 10','you are 10','they are 10']
In principle, same as passing a function:
data = ['we are 101','you are 102','they are 103']
print(list(map(f,data)))
but often faster and awesome. I love lambdas
Keep in mind, while explaining lambda is solved here, it is not the implementation of choice for your particular example. Suggestion:
f = open('feedback.txt', 'r')
feedback = f.read().splitlines()
f.close()
See also 'Reading a file without newlines'.

Replacing composed functions in Sympy

I am trying to generate some random expressions in the form f(g(x)). I'd like to be able to replace g with something like sin(x) or x**2 and f with something like cos(x) or log(x). So I'd get something like sin(cos(x)) or log(x**2) (but randomized).
The part of this task I'm having trouble with is replacing both an outer and inner function.
Here's my code:
import sympy
from sympy import abc
x = abc.x
f = sympy.Function('f')(x)
g = sympy.Function('g')(x)
full=f.subs(x, g)
newExpr = sympy.sin(x)
newExpr2 = sympy.cos(x)
print(full)
replaced_inner = full.subs(g, newExpr)
print(replaced_inner)
both = replaced_inner.subs(f, newExpr2)
print(both)
full prints f(g(x)) so that works
replaced_inner prints f(sin(x)) so that works as well
both prints f(sin(x)) when I want it to print cos(sin(x))
I've tried using args[0] and f.func but haven't made progress.
How can I replace both the inner and outer functions (and eventually more complex things like f(g(h(x))).
I could simply create cos(sin(x)) but I want to do it using variables so I can randomize what function gets replaced.
The problem is in confusion of functions like sympy.Function('f') and expressions like sympy.Function('f')(x). Having defined f = sympy.Function('f')(x) you made f the expression f(x). And since
the expression f(g(x)) does not have f(x) as a subexpression, attempted substitution fails.
All this is fixed if you work with actual functions, not plugging x in prematurely.
f = sympy.Function('f')
g = sympy.Function('g')
full = f(g(x))
newExpr = sympy.sin
newExpr2 = sympy.cos
print(full)
replaced_inner = full.subs(g, newExpr)
print(replaced_inner)
both = replaced_inner.subs(f, newExpr2)
print(both)
This prints
f(g(x))
f(sin(x))
cos(sin(x))
Aside: you may also be interested in replace method which supports certain patterns. Not necessary here, but may be necessary for more advanced replacements.

python, basic lambda function

I am a c++ guy, learning the lambda function in python and wanna know it inside out. did some seraches before posting here. anyway, this piece of code came up to me.
<1> i dont quite understand the purpose of lambda function here. r we trying to get a function template? If so, why dont we just set up 2 parameters in the function input?
<2> also, make_incrementor(42), at this moment is equivalent to return x+42, and x is the 0,1 in f(0) and f(1)?
<3> for f(0), does it not have the same effect as >>>f = make_incrementor(42)? for f(0), what are the values for x and n respectively?
any commments are welcome! thanks.
>>> def make_incrementor(n):
... return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43
Yes, this is similar to a C++ int template. However, instead of at compile time (yes, Python (at least for CPython) is "compiled"), the function is created at run time. Why the lambda is used in this specific case is unclear, probably only for demonstration that functions can be returned from other functions rather than practical use. Sometimes, however, statements like this may be necessary if you need a function taking a specified number of arguments (e.g. for map, the function must take the same number of arguments as the number of iterables given to map) but the behaviour of the function should depend on other arguments.
make_incrementor returns a function that adds n (here, 42) to any x passed to that function. In your case the x values you tried are 0 and `1``
f = make_incrementor(42) sets f to a function that returns x + 42. f(0), however, returns 0 + 42, which is 42 - the returned types and values are both different, so the different expressions don't have the same effect.
The purpose is to show a toy lambda return. It lets you create a function with data baked in. I have used this less trivial example of a similar use.
def startsWithFunc(testString):
return lambda x: x.find(testString) == 0
Then when I am parsing, I create some functions:
startsDesctription = startsWithFunc("!Sample_description")
startMatrix = startsWithFunc("!series_matrix_table_begin")
Then in code I use:
while line:
#.... other stuff
if startsDesctription(line):
#do description work
if startMatrix(line):
#do matrix start work
#other stuff ... increment line ... etc
Still perhaps trival, but it shows creating general funcitons with data baked it.

How can I automatically run all the functions in the module?

I need to run several functions in a module as follws:
mylist = open('filing2.txt').read()
noTables = remove_tables(mylist)
newPassage = clean_text_passage(noTables)
replacement = replace(newPassage)
ncount = count_words(replacement)
riskcount = risk_count(ncount)
Is there any way that I can run all the functions at once? Should I make all the functions into a big function and run that big function?
Thanks.
You should make a new function in the module which executes the common sequence being used. This will require you to figure out what input arguments are required and what results to return. So given the code you posted, the new function might look something like this -- I just guessed as to what final results you might be interested in. Also note that I opened the file within a with statement to ensure that it gets closed after reading it.
def do_combination(file_name):
with open(file_name) as input:
mylist = input.read()
noTables = remove_tables(mylist)
newPassage = clean_text_passage(noTables)
replacement = replace(newPassage)
ncount = count_words(replacement)
riskcount = risk_count(ncount)
return replacement, riskcount
Example of usage:
replacement, riskcount = do_combination('filing2.txt')
If you simply store these lines in a Python (.py) file you can simply execute them.
Or am I missing something here?
Creating a function is also easy to call them though:
def main():
mylist = open('filing2.txt').read()
noTables = remove_tables(mylist)
newPassage = clean_text_passage(noTables)
replacement = replace(newPassage)
ncount = count_words(replacement)
riskcount = risk_count(ncount)
main()
As far as I understood, use need function composition. There is no special function for this in Python stdlib, but you can do this with reduce function:
funcs = [remove_tables, clean_text_passage, replace, count_words, risk_count]
do_all = lambda args: reduce(lambda prev, f: f(prev), funcs, args)
Using as
with open('filing2.txt') as f:
riskcount = do_all(f.read())
Here's another approach.
You could write a general function somewhat like that shown in the First-class composition section of the Wikipedia article on Function composition. Note that unlike in the article the functions are applied in the the order they are listed in the call to compose().
try:
from functools import reduce # Python 3 compatibility
except:
pass
def compose(*funcs, **kwargs):
"""Compose a series of functions (...(f3(f2(f1(*args, **kwargs))))) into
a single composite function which passes the result of each
function as the argument to the next, from the first to last
given.
"""
return reduce(lambda f, g:
lambda *args, **kwargs: f(g(*args, **kwargs)),
reversed(funcs))
Here's a trivial example illustrating what it does:
f = lambda x: 'f({!r})'.format(x)
g = lambda x: 'g({})'.format(x)
h = lambda x: 'h({})'.format(x)
my_composition = compose(f, g, h)
print my_composition('X')
Output:
h(g(f('X')))
Here's how it could be applied to the series of functions in your module:
my_composition = compose(remove_tables, clean_text_passage, replace,
count_words, risk_count)
with open('filing2.txt') as input:
riskcount = my_composition(input.read())

Categories

Resources