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
Related
class well_2D:
def __init__(self,d):
self.d=d
def φ_x(self,l,x):
if l%2==0 :
return np.sqrt(2/self.d)*np.sin(np.pi*l*x/self.d)
else :
return np.sqrt(2/self.d)*np.cos(np.pi*l*x/self.d)
def φ_y(self,m,y):
if l%2==0 :
return np.sqrt(2/self.d)*np.sin(np.pi*m*y/self.d)
else :
return np.sqrt(2/self.d)*np.cos(np.pi*m*y/self.d)
def Ψ(self,l,m,x,y):
return φ_x*φ_y
Usage:
Q=well_2D(2)
Q.Ψ(2,1,2,2)
>>>TypeError: unsupported operand type(s) for *: 'function' and 'function'
Based on the function signatures, you meant to write this:
return self.φ_x(l, x) * self.φ_y(m, y)
BTW l is a bad variable name since it looks like 1 and I. You could use L instead.
For various reasons, you cannot multiply functions themselves, only the results of calling them. In this case, I would refactor your code significantly:
class Well2D:
def __init__(self, d):
self.d = d
def φ(self, l, x):
f = np.sin if l % 2 == 0 else np.cos
return np.sqrt(2/self.d) * f(np.pi * l * x / self.d)
def Ψ(self, l, m, x, y):
return self.φ(l, x) * self.φ(m, y)
Inside φ, the only difference between the two cases is the trigonometric function you call based on the parity of l. There is no difference between φ_x and φ_y, other than the arguments you pass to each call, so just define a single function φ.
I was wondering how I could manipulate a function to take a new argument in Python without modifying original formula.
For example, how would I take square function and make another function like multiply square using square function as a model:
Original Function:
def square(x):
result = (x*x)
return(result)
New Function, takes a new argument "y":
def multSquare(x,y):
result = y*square(x)
return(result)
I tried using decorators but I can't seem to have it working
def addArg(tarFun):
def wrapArg(y, *args, **kwargs):
result=tarFun(*args, **kwargs) * y
return result
return wrapArg
def square(x):
result = (x*x)
return(result)
multSquare = addArg(square)
print(square(2)) # This should be 4
print(multSquare(2,3)) # This should be 12
This doesn't work because I don't how to inject y.
In the end, I want to make a function that takes all the arguments of the original function plus one more argument.
Thanks everybody!
If you pay attention to the order of your arguments, what's happening is that you are squaring 3 and multiplying it by 2. This is because your function wrapArg uses the first argument (2) as the number you are multiplying with and the second (3) as the number you are squaring.
multSquare(3, 2) will give the result you want.
In additional to what busybear said you could just swap the parameters around
def addArg(fun):
def wrapArg(x, y):
result = fun(x) * y
return result
return wrapArg
def square(x):
result = (x * x)
return(result)
multSquare = addArg(square)
print(square(2)) # This should be 4
print(multSquare(2, 3)) # This should be 12
or additionally just use optional arguments
def square(x, y = None):
sq = x*x
if y:
sq *= y
return sq
from scipy.integrate import quad
def integrand(a, b):
return a * x ** 2 + b
a = 2
b = 1
I = quad(integrand, 0, 1, args=(a,b))
I
This is my program. When I tried to run it, it was showing error :
integrand () takes 2 positional arguments but 3 were given ....
I didn't understand why it is asking for 3 arguments when there are only two variables, i.e. a and b.
Can anyone help me? Can anyone clarify my doubts?
Just replace
def integrand(a, b):
by
def integrand(x, a, b):
The problem is that in the function, you use a variable x but you do not pass the variable x as an argument to the function. 0 and 1 acts as the limits of the integral but since you are integrating w.r.t. x, you get this error.
Output
(1.6666666666666667, 1.8503717077085944e-14)
a*x**2+b This function you are using contain a variable x, in your case def integrand(a, b): does not contain a variable x which uses 0 to 1 limits of the integral you are using on I=quad(integrand,0,1,args=(a,b)).
So all you have to do is add x to your def;
def integrand(x, a, b):
return a * x ** 2 + b
a = 2
b = 1
I = quad(integrand,0,1,args=(a,b))
I
I am studying the properties of functions in Python and I came across an exercise that asks to:
Write a function which returns de power of a number. Conditions: The function may only take 1 argument and must use another function to return the value of the power of a given number.
The code that solves this exercise is:
def power(x):
return lambda y: y**x
For example, if we would like to know the value of the power: 2^3, we would call the function like this: power(3)(2)
Here is what I would like to know:
Is there any way to write a function that, when called, has a similar structure: function()()().
In other words, is it possible to write a function, that requires three or more parentheses ()()() when called?
If it is possible, could you please give me an example code of that function and briefly explain it?
Also:
def power(x):
def power_extra(y):
return y
def power_another(z):
return z
return power_extra and power_another
Possible?
Sure you can:
def power_times(k):
"""use as power_times(k)(x)(y) => k * y^x"""
return lambda x: lambda y: k * y**x
print power_times(2)(3)(4) # returns 2 * 4^3 = 128
When you call this function with argument 2 (power_times(2)), it returns a lambda function that works like lambda x: lambda y: 2 * y ** x (that is, like your original function, only with an extra "times 2").
You can stack as many lambdas on top of each other as you like:
def many_lambdas(x):
"""many_lambdas(x)(y)(z)(q) => x + y * z^q"""
return lambda y: lambda z: lambda q: x + y * z ** q
print many_lambdas(1)(2)(3)(4) # prints 163
Indeed, it might be even clearer if you skipped using def at all, and just wrote:
many_lambdas = lambda x: lambda y: lambda z: lambda q: x + y * z ** q
Or, alternatively, you could skip using lambda ever and just use them as nested functions:
def many_funcs(x):
def many_funcs_y(y):
def many_funcs_z(z):
def many_funcs_q(q):
return x + y * z ** q
return many_funcs_q
return many_funcs_z
return many_funcs_y
print many_funcs(1)(2)(3)(4) # prints 163
#David's answer would aptly answer you question for fixed nested function calls. For undefined nesting, you may want to define a class and overload the __call__ method along with __repr__ and __int__ to serve your Purpose.
>>> class Power(object):
def __init__(self, value):
self.value = value
def __call__(self, value):
self.value **= value
return self
def __int__(self):
return self.value
def __repr__(self):
return str(self.value)
>>> print Power(2)(2)(2)(2)(2)
65536
>>> int(Power(2)(2)(2)(2)(2)) / 2
32768
I'm wondering if there exists a python module that would allow me to do something like this:
x = MagicNumber()
x.value = 3
y = 2 * (x + 2) ** 2 - 8
print y # 42
x.value = 2
print y # 24
So MagicNumber would implement all the special operator methods, and they would all return instances of MagicNumber, while keeping track of what operations are performed. Is there such a class?
EDIT: clarification
I want to use this in a module that should remember a lot of parameters of some arbitrary calculation that the user wishes to perform. So the user will set the parameters and then use them to produce his result. Then if he decides he'd like to alter a parameter, the change is reflected in his result immediately. So a very simplified usage session with only one parameter instance would look like:
p = MyParams()
p.distance = 13.4 # I use __getattr__ and __setattr__ such that
p.speed = 3.14 # __getattr__ returns MagicNumber instances
time = p.distance / p.speed
EDIT 2: more clarification
Okay, I'll do what I should have done from the start. I'll provide context.
You are an engineer and you're to produce a LaTeX document detailing the workings and properties of some prototype gadget. It is a task you'll do repeatedly for different prototypes. You write a small LaTeX python interface. For each prototype you create a python module that generates the requisite document. In it you type out the LaTeX code while calculating variables as they are needed, so that the calculations are in context. After a while you notice two problems:
The number of variables and parameters makes locals a mess and the variable names are hard to remember. You should group them into categories to keep track of them all.
You sometimes need to redo the same calculation, which is spread over the last couple of chapters and a dozen lines, with one or more parameters changed. You should find some way to avoid code duplication.
Out of this problem comes the original question.
Something like this?
import operator
MAKE_BINARY = lambda opfn : lambda self,other : BinaryOp(self, asMagicNumber(other), opfn)
MAKE_RBINARY = lambda opfn : lambda self,other : BinaryOp(asMagicNumber(other), self, opfn)
class MagicNumber(object):
__add__ = MAKE_BINARY(operator.add)
__sub__ = MAKE_BINARY(operator.sub)
__mul__ = MAKE_BINARY(operator.mul)
__radd__ = MAKE_RBINARY(operator.add)
__rsub__ = MAKE_RBINARY(operator.sub)
__rmul__ = MAKE_RBINARY(operator.mul)
# __div__ = MAKE_BINARY(operator.div)
# __rdiv__ = MAKE_RBINARY(operator.div)
__truediv__ = MAKE_BINARY(operator.truediv)
__rtruediv__ = MAKE_RBINARY(operator.truediv)
__floordiv__ = MAKE_BINARY(operator.floordiv)
__rfloordiv__ = MAKE_RBINARY(operator.floordiv)
def __neg__(self, other):
return UnaryOp(self, lambda x : -x)
#property
def value(self):
return self.eval()
class Constant(MagicNumber):
def __init__(self, value):
self.value_ = value
def eval(self):
return self.value_
class Parameter(Constant):
def __init__(self):
super(Parameter, self).__init__(0.0)
def setValue(self, v):
self.value_ = v
value = property(fset=setValue, fget=lambda self: self.value_)
class BinaryOp(MagicNumber):
def __init__(self, op1, op2, operation):
self.op1 = op1
self.op2 = op2
self.opn = operation
def eval(self):
return self.opn(self.op1.eval(), self.op2.eval())
class UnaryOp(MagicNumber):
def __init__(self, op1, operation):
self.op1 = op1
self.operation = operation
def eval(self):
return self.opn(self.op1.eval())
asMagicNumber = lambda x : x if isinstance(x, MagicNumber) else Constant(x)
And here it is in action:
x = Parameter()
# integer division
y = 2*x*x + 3*x - x//2
# or floating division
# y = 2*x*x + 3*x - x/2
x.value = 10
print(y.value)
# prints 225
x.value = 20
print(y.value)
# prints 850
# compute a series of x-y values for the function
print([(x.value, y.value) for x.value in range(5)])
# prints [(0, 0), (1, 5), (2, 13), (3, 26), (4, 42)]
You could give sympy, a computer algebra system written in Python, give a try.
E.g.
>>> from sympy import Symbol
>>> x = Symbol('x')
>>> y = 2 * (x + 2) ** 2 - 8
>>> y
2*(x + 2)**2 - 8
>>> y.subs(x,3)
42
>>> y.subs(x,2)
24
Isn't this called a function? This may sound like a simple answer, but I mean it sincerely.
def y(x):
return 2 * (x + 2) ** 2 - 8
Aren't you thinking in the wrong direction with this one?
To address the clarification:
class MyParams():
distance = 0.0
speed = 0.0
def __call__(self):
return self.distance / self.speed
p = MyParams()
p.distance = 13.4 # These are properties
p.speed = 3.14 # where __get__ returns MagicNumber instances
time = p() # 4.26
p.speed = 2.28
time = p() # 5.88
I guess I'm more in favor of this type of a solution, although I see the benefit in the sympy module. Preference, I guess.
>>> magic = lambda x: eval('2 * (x + 2) ** 2 - 8')
>>> magic(2)
24
>>> magic(3)
42
>>> magic = lambda x: eval('x ** 4')
>>> magic(2)
16
>>> magic(3)
81
I think the difficulty is in "how to keep operators priority" rather than implementing a class.
I suggest to look at a different notation (like Reverse Polish Notation) that may help in getting rid of priority issues...