pass multiple parameters to function in multiple tuple sets - python - python

essentially I have a function which I need to pass to a bunch of values in two different moments (here skipped for practical reasons), hence, I thought need to split all the parameters in two tuple sets after which I'd pass the first set and then the second thinking - mistakenly - that python would allocate all the available n parameters of the function to the values passed with the tuple and then the rest with the second tuple. That is not the case:
def example_F_2(x, y, z, g):
return x * y + z * g
e = (1,2)
r = (3,4)
print(example_F_2(e, r))
in fact:
Traceback (most recent call last):
File "C:/Users/francesco/PycharmProjects/fund-analysis/test_sheet.py", line 7, in <module>
print(example_F_2(e, r))
TypeError: example_F_2() missing 2 required positional arguments: 'z' and 'g'
what can I do? I am guessing something from this page should work (https://docs.python.org/3.5/library/functools.html) but I have been unable to do it myself

A very simple way is to concatenate the tuples and then unpack them as you pass them to your function:
print(example_F_2(*(e+r)))

Perhaps you can use something like this:
def example_F_2(e=None, r=None):
first_term = 0
second_term = 0
if e is not None:
first_term = e[0] * e[1]
if r is not None:
second_term = r[0] * r[1]
return first_term + second_term
e = (1, 2)
r = (3, 4)
print example_F_2(e, r)
> 14
print example_F_2(e=e)
> 2
print example_F_2(r=r)
> 12

Related

How to pass a function as an argument

I would like to find an approximate value for the number pi = 3.14.. by using the Newton method. In order to use it also for some other purpose and thus other function than sin(x), the aim is to implement a generic function that will be passed over as an argument. I have an issue in passing a function as an argument into an other function. I also tried lambda in different variations. The code I am showing below produces the error message: IndexError: list index out of range. I will appreciate your help in solving this issue and eventually make any suggestion in the code which may not be correct. Thanks.
from sympy import *
import numpy as np
import math
x = Symbol('x')
# find the derivative of f
def deriv(f,x):
h = 1e-5
return (lambda x: (f(x+h)-f(x))/h)
def newton(x0,f,err):
A = [x0]
n = 1
while abs(A[n]-A[n-1])<=err:
if n == 1:
y = lambda x0: (math.f(x0))
b = x0-y(x0)/(deriv(y,x0))
A.append(b)
n += 1
else:
k = len(A)
xk = A[k]
y = lambda xk: (math.f(xk))
b = newton(A[k],y,err)-y(newton(A[k],y,err))/deriv(y,k)
A.append(b)
n += 1
return A, A[-1]
print(newton(3,math.sin(3),0.000001))
I don't know why you use sympy because I made it without Symbol
At the beginning you have to calculate second value and append it to list A and later you can calculate abs(A[n]-A[n-1]) (or the same without n: abs(A[-1] - A[-2])) because it needs two values from this list.
Other problem is that it has to check > instead of <=.
If you want to send function sin(x) then you have to use math.sin without () and arguments.
If you want to send function sin(3*x) then you would have to use lambda x: math.sin(3*x)
import math
def deriv(f, x, h=1e-5):
return (f(x+h) - f(x)) / h
def newton(x0, f, err):
A = [x0]
x = A[-1] # get last value
b = x - (f(x) / deriv(f, x)) # calculate new value
A.append(b) # add to list
while abs(A[-1] - A[-2]) > err: # it has to be `>` instead of `<=`
x = A[-1] # get last value
b = x - (f(x) / deriv(f, x)) # calculate new value
A.append(b) # add to list
return A, A[-1]
# sin(x)
print(newton(3, math.sin, 0.000001)) # it needs function's name without `()`
# sin(3*x)
print(newton(3, lambda x:math.sin(3*x), 0.000001))
# sin(3*x) # the same without `lambda`
def function(x):
return math.sin(3*x)
print(newton(3, function, 0.000001))
Result:
([3, 3.1425464414785056, 3.1415926532960112, 3.141592653589793], 3.141592653589793)
([3, 3.150770863559604, 3.1415903295877707, 3.1415926535897936, 3.141592653589793], 3.141592653589793)
EDIT:
You may write loop in newton in different way and it will need <=
def newton(x0, f, err):
A = [x0]
while True:
x = A[-1] # get last value
b = x - (f(x) / deriv(f, x)) # calculate new value
A.append(b) # add to list
if abs(A[-1] - A[-2]) <= err:
break
return A, A[-1]

'NoneType' object is not iterable - where is an error?

My aim is to take a triple (A, B, C), compute three "neighbours", and then output the maximum of each of those neighbours to a list.
For example, the neighbours of (sqrt(6), 4*sqrt(3), 9*sqrt(2)) are
(sqrt(3)*sqrt(2), 3*sqrt(2), 4*sqrt(3))
(4*sqrt(3), 35*sqrt(3)*sqrt(2), 9*sqrt(2))
(sqrt(3)*sqrt(2), 9*sqrt(2), 14*sqrt(3))
so the values 14*sqrt(3), 36*sqrt(6), 4*sqrt(3) would be the output.
When I try this:
A = 1*sqrt(6)
B = 4*sqrt(3)
C = 9*sqrt(2)
def nbhs_1(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((X.canonicalize_radical(), (X * Y - Z).canonicalize_radical(), Y.canonicalize_radical()))
def nbhs_2(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((Y.canonicalize_radical(), (Y * Z - X).canonicalize_radical(), Z.canonicalize_radical()))
def nbhs_3(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((X.canonicalize_radical(), Z.canonicalize_radical(), (X * Z - Y).canonicalize_radical()))
result_1 = nbhs_1((A, B, C))
result_2 = nbhs_2((A, B, C))
result_3 = nbhs_3((A, B, C))
print(result_1)
print(result_2)
print(result_3)
l = [max(result_1), max(result_2), max(result_3)]
I get 'NoneType' object is not iterable.
The main problem is that you are not structuring the function properly:
It is recommended that you expose your arguments within the function call. Don't def nbhs_1(triple), do instead def nbhs_1(X, Y, Z). In this way you can actually have one single function that does what you want (easier to maintain)
Return your result. At the moment you are printing the outcome of the function call but you are not returning those results.
I'm also not sure the canonicalize_radical() call is also done properly. Python is object-oriented and by writing var.canonicalize_radical() you are inferring that var should itself know about this function (e.g. the function is part of var) but that sounds wrong. The correct call may be canonicalize_radical(var)
Basically, this should be closer to a correct solution:
A=1*sqrt(6)
B=4*sqrt(3)
C=9*sqrt(2)
def nbhs(X, Y, Z):
out1 = canonicalize_radical(X)
out2 = canonicalize_radical(X*Y-Z)
out3 = canonicalize_radical(Y)
return out1, out2, out3
l = [max(nbhs(A, B, C)), max(nbhs(B, A, C)), max(nbhs(C, B, A))]
The problem is that you are not calling the functions nbhs_1, nbhs_2, and nbhs_3 and also the functions aren't returning any values
from math import sqrt
A=1*sqrt(6)
B=4*sqrt(3)
C=9*sqrt(2)
triple = (A, B, C)
def nbhs_1(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (X.canonicalize_radical(),(X*Y-Z).canonicalize_radical(),Y.canonicalize_radical())
def nbhs_2(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (Y.canonicalize_radical(),(Y*Z-X).canonicalize_radical(),Z.canonicalize_radical())
def nbhs_3(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (X.canonicalize_radical(),Z.canonicalize_radical(),(X*Z-Y).canonicalize_radical())
l=[max(nbhs_1(triple)),max(nbhs_2(triple)),max(nbhs_3(triple))]

How to compute the following equation correctly?

Using python 2.7 I am trying to compute the following rather difficult set of equations.
I have successfully implemented the first two, but am struggling with the third. Here is my attempt,
def pi_tau( r ):
return (1 - (1 - r)**(t + 1))/(2 - r)
def mean_field( r ):
return 1 - (1 - r)**t
def pi_neighbour( r ):
inside = []
for kappa_dash in range(0, kappa - 1):
Binomial_Coefficient = (math.factorial(kappa - 1)) / (math.factorial(kappa - 1 - kappa_dash)*math.factorial(kappa_dash))
top = ((mean_field( r )*pi_tau( r ))**kappa_dash)*(1 - mean_field( r )*pi_tau( r ))**(kappa - 1 - kappa_dash)
bottom = kappa_dash + 1
fraction = top/bottom
inside.append(kappa_dash)
inside[kappa_dash] = inside[kappa_dash] + fraction*Binomial_Coefficient
return pi_tau*inside
I then try to call this function
# set parameters
r = 0.15
kappa = 2.1
T = 10
ppp_t = []
mmm_f = []
nnn_t = []
for t in range(0, T):
ppp_t.append(pi_tau( r ))
mmm_f.append(mean_field( r ))
nnn_t.append(pi_neighbour( r ))
I get the following error message
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-41-9bcf462306f0> in <module>()
6 ppp_t.append(pi_tau( r ))
7 mmm_f.append(mean_field( r ))
----> 8 nnn_t.append(pi_neighbour( r ))
<ipython-input-39-d9acdd7490f9> in pi_neighbour(r)
19 inside[kappa_dash] = inside[kappa_dash] + fraction*Binomial_Coefficient
20
---> 21 return pi_tau*inside
TypeError: can't multiply sequence by non-int of type 'function'
I am looking for any advice on how to implement the third function and improve on my method.
There are several weird things here:
you calculate the top, bottom, and bionomial all in the for loop, but don't sum up in that for loop; and
you multiply the pi_tau function with a list?
return pi_tau*inside
you use range(0, kappa - 1), but the upperbound of range(..) is exclusive
Nevertheless, you make things quite hard. You could use the following approach:
from math import factorial
def pi_neighbour(r):
sum = 0.0
for kappa_dash in range(0,kappa):
bin_coeff = factorial(kappa-1)/(factorial(kappa-1-kappa_dash)*factorial(kappa_dash))
top = ((mean_field(r)*pi_tau(r))**kappa_dash)*(1-mean_field(r)*pi_tau(r))**(kappa-1-kappa_dash)
sum += bin_coeff*top/(kappa_dask+1)
return pi_tau(r)*sum
What I believe you meant to do is the following in line 21 of the traceback:
return pi_tau(r)*inside
You forgot to call the function, and so it is attempting to multiply an integer by a function, rather than the return value of the function.
The error is that you are multiplying a list, that is inside and a integer, that is return of pi_tau(r)
Do this instead (a list comprehension)
try this:
return [i*pi_tau(r) for i in inside]

Dictionary changing size during iteration and I don't know why

Here's the error message:
RuntimeError: dictionary changed size during iteration
Here's the segment of my code (<= marks the error line):
# Probability Distribution from a sequence of tuple tokens
def probdist_from_tokens (tokens, N, V = 0, addone = False):
cfd = ConditionalFreqDist (tokens)
pdist = {}
for a in cfd: # <= line with the error
pdist[a] = {}
S = 1 + sum (1 for b in cfd[a] if cfd[a][b] == 1)
A = sum (cfd[a][b] for b in cfd[a])
# Add the log probs.
for b in cfd[a]:
B = sum (cfd[b][c] for c in cfd[b])
boff = ((B + 1) / (N + V)) if addone else (B / N)
pdist[a][b] = math.log ((cfd[a][b] + (S * boff)) / (A + S))
# Add OOV for tag if relevant
if addone:
boff = 1 / (N + V)
pdist[a]["<OOV>"] = math.log ((S * boff) / (A + S))
return pdist
I'm basically just using cfd as a reference to put the correct values in pdist. I'm not trying to change cfd, I just want to iterate over it's keys and the keys of it's sub dictionary.
I think the problem is caused by the lines where I set the variables A and B, I got the same error when I had different code on those lines but I don't get the error when I replace them with a constant value.
nltk.probability.ConditionalFreqDist inherits defaultdict, which means if you read a non-existing entry cfd[b], a new entry (b, FreqDist()) will be inserted to the dictionary, and thus changing its size. Demonstration of the problem:
import collections
d = collections.defaultdict(int, {'a': 1})
for k in d:
print(d['b'])
Output:
0
Traceback (most recent call last):
File "1.py", line 4, in <module>
for k in d:
RuntimeError: dictionary changed size during iteration
So you should check this line:
for b in cfd[a]:
B = sum (cfd[b][c] for c in cfd[b])
are you sure the b key really exists in cfd? You may want to change it to
B = sum(cfd[b].values()) if b in cfd else 0
# ^~~~~~~~~~~

How can I use the result from a function in another function? [duplicate]

This question already has answers here:
How do I get a result (output) from a function? How can I use the result later?
(4 answers)
Closed 6 months ago.
Suppose I have a function like:
def eklid(p, a, b,):
x = [1, 0]
y = [0, 1]
r = [a, b]
q = [0]
n = 0
while r[n+1] != 0:
q.append(r[n] // r[n+1])
r.append(r[n] % r[n+1])
x.append(x[n] - x[n+1] * q[n+1])
y.append(y[n] - y[n+1] * q[n+1])
if p == 0:
print(r[n], "=", r[n+1], "*", q[n+1], "+", r[n+2])
elif p == 1: # extended print
print(r[n+2], "\t", x[n+2], "\t", y[n+2], "\t", r[n+2], "=", a, "*", x[n+2], "+", b, "*", y[n+2])
elif p == -1:
k =1
else:
print("wrong input")
n += 1
return x, y, r, q, n,
I want to use x and r from it in this function:
def cong_solv(x, r, b,):
result = x/r
int_result = int(result)
return int_result
How can I do that?
# Here, a=x, b=y, c=r, d=q, e=n
a, b, c, d, e = eklid(h, i, k)
# Assuming based on your function definitions you want the
# same value as the third argument
final_result = cong_solv(a, c, k)
You get the return values from eklid and save them into variables. You then use those variables to call the next function.
Of course, in a real code you should name your varialbes better than I did in this example. I deliberately did not call the variables the same names as inside the function to demonstrate that you don't have to.
One way would be to call the eklid() function from inside the cong_solv() function. Something like this should work:
def cong_solv(x, r, b):
p = "foo"
b = "bar"
x, y, r, q, n = eklid(p, a, b)
result = x/r
int_result = int(result)
return int_result
In python, when you return more than one variable, it returns a tuple.
You can retrieve the value by its index (returned_value[0], returned_value[1]) or unpack the tuple like Mike Driscoll said (a, b, c, d = eklid(h, i, k)).
Since I got two downvotes, I am going to give you better (I hope) explanation:
Everytime you return more than one value, it returns a tuple.
def my_function():
a = 10
b = 20
return a, b
print type(my_function()) # <type 'tuple'>
But if you return just one value:
def my_function():
a = 10
return a
print type(my_function()) # <type 'int'>
So if you want to use your value, you can:
Unpack tuple values like this
a, b = my_function()
This way you get your return values in the same order you return inside my_function.
Rewriting your code, you can simply do:
a, b, c = eklid(10, 20, 30) # it will return a tuple
And call your other function:
cong_solv(a, b, 20)
In my honest opinion I would return a dict. With dict you can be explicit because your values have key names.
Inside your eklid return function:
return d # d = {"what_x_means": x,
# "what_y_means": y,
# "what_r_means": r,
# "what_q_means": q,
# "what_n_means": n}
And retrieve for its key:
d["what_x_means"]
d["what_r_means"]
Similar to How do you return multiple values in Python?
Return as an tuple (x,y,r....) or an array and assign to tuple / array respectively.
Or assign them to class variables and access them

Categories

Resources