Python returning variables from various functions - python

from __future__ import division
import math
def main():
the_discriminant = discrim(1,0,-4)
print the_discriminant
the_rest(discrim,b,a)
def discrim(a,b,c):
discriminant = math.sqrt(math.pow(b,2)-4*a*c)
return discriminant, b,a
def the_rest(discrim,b,a):
x = ((-b + discriminant) / 2*a)
y = ((-b - discriminant) / 2*a)
print x,y
if __name__ == '__main__':
main()
I am fairly new to Python, and I'm playing with writing functions and returning variables, I'm a little confused on how to correct the code. I am writing a quadratic solver program, but I need to use the discriminant and a,b,c values in "the rest" function. (which does the rest of the equation.) I'm kind of confused on how to return the values and use them in another function. Thanks!

the_rest(*the_discriminant)
or (and I prefer this method):
d, b, a = discrim(1, 0, -4)
the_rest(d, b, a)

I believe this is what you're trying to do. your discrim function returns a tuple (similar to an array). Then when you call the_rest using a * indicates that you want to send the elements of the tuple, rather than the tuple itself as one argument
from __future__ import division
import math
def main():
the_discriminant = discrim(1,0,-4)
print the_discriminant
the_rest(*the_discriminant)
def discrim(a,b,c):
discriminant = math.sqrt(math.pow(b,2)-4*a*c)
return discriminant, b,a
def the_rest(discrim,b,a):
x = (-b + discrim) / (2*a)
y = (-b - discrim) / (2*a)
return x, y
if __name__ == '__main__':
main()

while jamylak's answer is correct, it can also be much more maintainable to return a simple class. Then if you ever change your function/return values/representation, the calling code:
is name/identifier-based; it is very flexible to change; its not order dependent, or tuple length dependent. It is also saves you typing and unnecessary duplication of ordering implied rules throughout your code.
if there IS a breaking change the interpreter will error on module load instead of at runtime, so you are not going to miss the error. This is because you are trying to access named members, and are not relying on some "hidden" or "implied" rule like tuple ordering that is not formalised anywhere in the code.
For a larger project this is definitely the way to go.

There's nothing wrong with returning tuples like in your version of discrim. But the code just doesn't make as much sense (IMO) that way.
Try it like so:
#!/usr/bin/env python
from __future__ import division
import math
def main():
a = 1
b = 0
c = -4
the_discriminant = discrim(a, b, c)
print the_discriminant
x, y = the_rest(the_discriminant,b,a)
print x, y
def discrim(a,b,c):
discriminant = math.sqrt(math.pow(b,2)-4*a*c)
return discriminant
def the_rest(d, b,a):
x = ((-b + d) / 2*a)
y = ((-b - d) / 2*a)
return x,y
if __name__ == '__main__':
main()

Related

print depending how many arguments given

Python beginner here trying to learn by doing, here i have two functions 'main','area'.
the one which has two arguments should print y = math.pi *a*b and the one which does not have two arguments should print x = math.pi *a**2 in my code it is currently printing like this " First (153.93804002589985, 0.0)
Second (78.53981633974483, 62.83185307179586) " (why its printing these 0.0 and 78.53981633974483?), how to make it check that if one parameter is given do this and if two do that ?
import math
def area(a,b=0):
y = math.pi *a*b
x = math.pi *a**2
return x,y
def main():
print("First", area(7))
print("Second", area(5, 4))
main()
If I understand you correctly, you want something like this:
import math
def area(a, b=None):
if b is None:
# b not specified:
x = math.pi * a**2
else:
# b specified:
x = math.pi * a*b
return x
def main():
print("First", area(7))
print("Second", area(5, 4))
main()
Output is
First 153.93804002589985
Second 62.83185307179586
When b is not specified, it is set to None. Then you test for that in the function.
The reason it prints e.g. (153.93804002589985, 0.0) in your original example is that you return a tuple (x, y) from the function with return x,y.
Your function returns a tuple, but the caller of the functions does not know which value to use. Instead, your function should just return either one or the other value, depending on the provided inputs. Also, I would suggest using None as the default for b since 0 might be a valid value.
def area(a, b=None):
if b is None:
return math.pi * a**2
else:
return math.pi * a * b
Alternatively, you could also use a ternary ... if ... else ... for either the entire expression or just the part that is different:
def area(a, b=None):
return math.pi * a * (b if b is not None else a)
The output will then be just
First 153.93804002589985
Second 62.83185307179586

Is there an alternative to exec in python?

So I'm making an integrator program with the simpson 1/3 method and I want the user to give me a function and interval of integration, and then return the result. I figure that I can use exec to make dynamic code, so I use it to create the function. This is my code:
from math import *
class CreaFormula:
def __init__(self,formula):
self.fun = "def f(x):\n return %s" % formula
class Integrador:
def __init__(self,f):
#integration interval
a = 0
b = 1
n = 600
h = (b-a)/n
#method
self.s = f(a) + f(b)
for i in range(1,n):
if i%2 == 0:
self.s = self.s + 2*f(a+i*h)
else:
self.s = self.s + 4*f(a+i*h)
self.s = self.s*(h/3)
vr = -cos(1) + e
self.er = abs((vr -self.s) /vr)
formula = input()
MiFo = CreaFormula(formula)
f1 = MiFo.fun
exec(f1)
MyInt = Integrador(f)
a = MyInt.s
b = MyInt.er
print(a)
So basically I want to put everything that is at the end of the code inside a class, so I can call it later by another code, but if I do that it shows an error that f is not defined, because it is created with exec. So is there a way to not use exec but still create a function from user's input?
Thanks in advance
If the question is just how to construct a function object that can evaluate a user-supplied expression, you'll probably have an easier time using eval than exec:
def create_function_from_formula(formula):
def user_function(x):
return eval(formula, globals(), {'x': x})
return user_function
Of course, even with eval, if someone provides a malicious formula, it can do anything, up to and including executing any other program included on the computer. So only do this if you trust the person providing the formula to essentially take over your computer. In particular, you should never do this if formula can come from a user who is not physically logged in to your computer already.

Program restarts when a function returns

I've made a program which does Pythagoras theorem for you if you just insert the lengths of the sides.
from math import *
def pythag(a , b):
c = sqrt(a^2 + b^2)
return c
print(pythag(3,4)) # added this as recommended in comment
But when I run it, this happens:
RESTART: C:/Users/Andrei/Documents/USB Backup/Python/Ultimate Calculator/functions2.py
5.0
I'm a noob at python so I don't really see the problem with the code.
You've written a function that does what you say but you're not actually calling it anywhere. The top level statements in your program are an import and a def and only those are called when you "run" it.
You have to run the function after the code you already have (e.g. for values 3 and 4):
from math import *
def pythag (a, b):
c = sqrt(a**2 + b**2)
return c
print(pythag(3,4))
Rather than importing math you could use the power signs.
For example:
def pythag(a , b):
c = (a**2 + b**2)**0.5
return c
print(pythag(3,4))

Double sum in Python

I am now programming on BFGS algorithm, where I need to create a function with a doulbe sum. I need to return a FUNCTION but not a number, so something like sum+= is not acceptable.
def func(X,W):
return a function of double sum of X, W
A illustrative example:
X = np.array([[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4],[5,5,5,5]])
W = np.array([[1,1,1,1],[2,2,2,2],[3,3,3,3]])
I want to get a function that, for each instance X[i] in X, and for each W[j] in W, return a function of the sum of numpy.dot(X[i],W[j]). For example, X[1] dot W[2] shoulde be 2*3+2*3+2*3+2*3
----------This contend is edited by me:-------------
When I saw the answers provided below, I think my question is not clear enough. Actually, I want to get a function:
Func = X[0]W[0]+X[0]W[1]+X[0]W[2]+ X[1]W[0]+X[1]W[1]+X[1]W[2]+
X[2]W[0]+X[2]W[1]+X[2]W[2]+ X[3]W[0]+X[3]W[1]+X[3]W[2] +
X[4]W[0]+X[4]W[1]+X[4]W[2]
-------------------end the edited content--------------
If I only got one dimension of W, the problem is easy by using numpy.sum(X,W).
However, how can I return a function of two sums with Python?
If you want to return the function f(i,j) -> X[i].W[j] :
def func(X,W):
def f(i,j): return np.dot(X[i],W[j])
return f
will work.
EDIT:
The VALUE you name Func in your edit is computed by sum([np.dot(x,w) for x in X for w in W]) or, more efficient, np.einsum('ij,kj->',X,W) .
if you want to return the FUNCTION that return Func, you can do it like that :
def func(X,W):
Func=np.einsum('ij,kj->',X,W)
return lambda : Func
Then f=func(X,W); print(f()) will print 360, the value named Func in your example.
If I got your question right, this should do exactly what you want (python-2.7):
import numpy as np
def sample_main():
X = np.array([[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4],[5,5,5,5]])
W = np.array([[1,1,1,1],[2,2,2,2],[3,3,3,3]])
f = lambda i, j : reduce (lambda a, b: a+b, map(lambda x, w: x*w, X[i], W[j]), 0)
return f
if __name__ == '__main__':
f = sample_main()
print (f(0, 0))
Just replace the sample_main function with your function that takes X and W.
Actually, I want to implement L_BFGS algorithm in my Python code. Inspired by the two answers provided by #B.M. and #siebenschlaefer, I figure out how to implement in my code:
func = np.sum(np.sum(log_p_y_xz(Y[i][t], Z[i], sigma_eta_ti(X[i],w[t],gamma[t]))+log_p_z_x(alpha, beta, X[i]) for t in range(3)) for i in range (5))
Please do not mind the details of the formula, what I want to say is that, I use two sum here and just using i in rage (5) and t in range (3) to tell the code do the sums.
Thanks again for the answers provided by #B.M. and #siebenschlaefer!!

How can I pass functions or operators as arguments to a function in Python?

...while still leaving it executable within the function.
The idea behind this is I want to create a summation function. Here's what I have so far:
def summation(n, bound, operation):
if operation is None and upper != 'inf':
g = 0
for num in range(n, limit + 1):
g += num
return g
else:
pass
But summations are most often about infinite convergent series (for which I use 'inf'), with operations applied to each term. Ideally, I'd like to be able to write print summation(0, 'inf', 1 / factorial(n)) and get the mathematical constant e, or def W(x): return summation(1, 'inf', ((-n) ** (n - 1)) / factorial(n)) to get the Lambert W function.
All that comes to my mind is passing the appropriate arithmetic as a string and then using the exec statement to execute it. But I don't think that would accomplish the whole thing, and it's obviously dangerous to use exec with possibly user-entered code.
In Python, functions are first-class, which is to say they can be used and passed around like any other values, so you can take a function:
def example(f):
return f(1) + f(2)
To run it, you could define a function like this:
def square(n):
return n * n
And then pass it to your other function:
example(square) # = square(1) + square(2) = 1 + 4 = 5
You can also use lambda to avoid having to define a new function if it's a simple expression:
example(lambda n: n * n)

Categories