Lambda function containing if statement - python

Is there any way how to code recursive function containing if with lamba?
Is possible to rewrite this using lambda.
def factorial(x):
if x <= 1:
return 1
return x * factorial(x - 1)
print(factorial(5))

No, or at least not without assigning the function to a variable and then using that name to call it. But you still cannot use any statements in the function.
In any case, don't do that. A lambda function is exactly like a normal def function in Python besides the restriction that it cannot contain statements.
The only reason to use a lambda in Python is to avoid defining an named function if you just need a simple callable returning some value.

Yes, it is possible for this specific case.
>>> factorial = lambda x: 1 if x < 1 else x * factorial(x - 1)
>>> factorial(5)
120
I wouldn't recommend it though. A standard function definition seems far more readable to me.

>>> l = lambda i: 1 if i<=1 else i * l(i-1)
>>> l(5)
120
>>> 5*4*3*2*1
120

Related

lambda function of another function but force fixed argument

I just switched to Python from Matlab, and I want to use lambda function to map function f1(x,y) with multiple arguments to one argument function f2(x) for optimization.
I want that when I map the function f2(x) <- f1(x,y=y1) then y will stay constant no matter what y1 changes, in Matlab this is true by default but if I try in Python, it keeps changing as the following examples
>>> def f1(x,y):
>>> return (x+y)
>>> y1 = 2
>>> f2 = lambda x: f1(x,y1)
>>> f2(1)
3
I expect f2(1) stays 3 even if I change y1, however if I change y1, the whole f1(1) also changes as follows
>>> y1 = 5
>>> f2(1)
6
I wonder is there a way that when I declare f2 = lambda x: f1(x,y1) then f1 will take the value of y1 at that time and fix it to f2. The reason for this because I want to dynamically create different functions for different scenarios then sum them all.
I'm still new to Python, please help, much appreciate.
Try:
f2 = lambda x, y=y1: f1(x,y)
Your issue has to do with how closures work in Python
Your version of the lambda function will use the current version of y1. You need to capture the value of y1 on the line where you've defined the lambda function. To do that, you can define it as the default value of a parameter (the y=y1 part).
As already pointed out, your issue comes down to how closures work. However, you really shouldn't be using a lambda for this - lambdas are for anonymous functions. Make a higher-order function with def statements instead:
>>> def f1(x,y):
... return x + y
...
>>> def f1_factory(y):
... def f1_y(x):
... return f1(x,y)
... return f1_y
...
>>> f1_factory(6)(4)
10
>>> f1_factory(5)(4)
9
It also avoids the problem you encountered:
>>> y = 3
>>> newfunc = f1_factory(y)
>>> newfunc(1)
4
>>> y = 20
>>> newfunc(1)
4
>>>
From PEP8:
Always use a def statement instead of an assignment statement that
binds a lambda expression directly to an identifier.
Yes:
def f(x): return 2*x
No:
f = lambda x: 2*x
The first form means that the name of the resulting
function object is specifically 'f' instead of the generic <lambda>.
This is more useful for tracebacks and string representations in
general. The use of the assignment statement eliminates the sole
benefit a lambda expression can offer over an explicit def statement
(i.e. that it can be embedded inside a larger expression)

Creating a copy of a function with some vars fixed

Assume I have a function
def multiply_by(x, multiplier):
return x * multiplier
How can I create a copy of that function and fix the multiplier in that function?
multiply_by_5 = multiply_by? <-- here I need python magic
such that multiply_by_5 would have only one argument x and the multiplier would be 5? So that
multiply_by_5(2)
10
Is there a way in Python 2.7 to do that?
You can use functools.partial with keyword argument:
>>> def multiply_by(x, multiplier):
... return x * multiplier
...
>>> from functools import partial
>>> multiply_by_5 = partial(multiply_by, multiplier=5)
>>> multiply_by_5(2)
10
functools.partial is made exactly for this.
you can use it like
import functools
multiply_by_5=functools.partial(multiply_by,multiplier=5)
As suggested by #niemmi's answer, functools.partial is probably the way to go.
However, similar work can be done using curried functions:
def multiply_by(multiplier):
def multiply(x):
return multiplier * x
return multiply
>>> multiply_by_5 = multiply_by(5) # no magic
>>> multiply_by_5(2)
10
Or using the lambda syntax:
def multiply_by(multiplier):
return lambda x: multiplier * x
Note that partial is more succinct, more efficient, and more directly express your intent in a standard way. The above technique is an example of the concept called closure, which is means that a function defined in inner scope may refer to variables defined in enclosing scopes, and "close" over them, remembering them, and even mutating them.
Since this technique is more general, it might take the reader of your code more time to understand what exactly do you mean in your code, since your code may be arbitrarily complicated.
Specifically for multiplication (and other operators) partial can be combined with operator.mul:
>>> import functools, operator
>>> multiply_by_5 = functools.partial(operator.mul, 5)
>>> multiply_by_5(2)
10
Here's an alternative that doesn't use functools.partial. Instead we define a function inside a function. The inner function "remembers" any of the local variables of the outer function that it needs (including the outer function's arguments). The magic that makes this happen is called closure.
def multiply_factory(multiplier):
def fixed_multiply(x):
return x * multiplier
return fixed_multiply
multiply_by_3 = multiply_factory(3)
multiply_by_5 = multiply_factory(5)
for i in range(5):
print(i, multiply_by_3(i), multiply_by_5(i))
output
0 0 0
1 3 5
2 6 10
3 9 15
4 12 20
If you want, you can use your existing multiply_by function in the closure, although that's slightly less efficient, due to the overhead of an extra function call. Eg:
def multiply_factory(multiplier):
def fixed_multiply(x):
return multiply_by(x, multiplier)
return fixed_multiply
That can be written more compactly using lambda syntax:
def multiply_factory(multiplier):
return lambda x: multiply_by(x, multiplier)
If you cannot change the multiply_by() function, the simplest and perhaps best way is probably
def multiply_by_5(x):
return multiply_by(x, 5)
You can also use lambda if you really want a one-liner.
However, you may want to change your first function to
def multiply_by(x, multiplier = 5):
return x * multiplier
Then you can do either of these:
print(multiply_by(4, 3))
12
print(multiply_by(2))
10

Python: Why does a lambda define the variable in an inline if?

Toying around with lambdas in Python I discovered that the following code is legal in Python 2.7.3 and returns the lambda:
x = lambda: 1 if x else 2
Why does the lambda define x when used in this way?
Edit: Python syntax is apparently too hard for me, see the accepted answer…
Why does the lambda define x when used in this way?
It doesn't. The assignment x = [any expression] defines x to be [any expression]. In this case, the expression is lambda: 1 if x else 2, which evaluates to a function object without arguments, and it is that which x holds.

Python functions within lists

So today in computer science I asked about using a function as a variable. For example, I can create a function, such as returnMe(i) and make an array that will be used to call it. Like h = [help,returnMe] and then I can say h1 and it would call returnMe("Bob"). Sorry I was a little excited about this. My question is is there a way of calling like h.append(def function) and define a function that only exists in the array?
EDIT:
Here Is some code that I wrote with this!
So I just finished an awesome FizzBuzz with this solution thank you so much again! Here's that code as an example:
funct = []
s = ""
def newFunct(str, num):
return (lambda x: str if(x%num==0) else "")
funct.append(newFunct("Fizz",3))
funct.append(newFunct("Buzz",5))
for x in range(1,101):
for oper in funct:
s += oper(x)
s += ":"+str(x)+"\n"
print s
You can create anonymous functions using the lambda keyword.
def func(x,keyword='bar'):
return (x,keyword)
is roughly equivalent to:
func = lambda x,keyword='bar':(x,keyword)
So, if you want to create a list with functions in it:
my_list = [lambda x:x**2,lambda x:x**3]
print my_list[0](2) #4
print my_list[1](2) #8
Not really in Python. As mgilson shows, you can do this with trivial functions, but they can only contain expressions, not statements, so are very limited (you can't assign to a variable, for example).
This is of course supported in other languages: in Javascript, for example, creating substantial anonymous functions and passing them around is a very idiomatic thing to do.
You can create the functions in the original scope, assign them to the array and then delete them from their original scope. Thus, you can indeed call them from the array but not as a local variable. I am not sure if this meets your requirements.
#! /usr/bin/python3.2
def a (x): print (x * 2)
def b (x): print (x ** 2)
l = [a, b]
del a
del b
l [0] (3) #works
l [1] (3) #works
a (3) #fails epicly
You can create a list of lambda functions to increment by every number from 0 to 9 like so:
increment = [(lambda arg: (lambda x: arg + x))(i) for i in range(10)]
increment[0](1) #returns 1
increment[9](10) #returns 19
Side Note:
I think it's also important to note that this (function pointers not lambdas) is somewhat like how python holds methods in most classes, except instead of a list, it's a dictionary with function names pointing to the functions. In many but not all cases instance.func(args) is equivalent to instance.__dict__['func'](args) or type(class).__dict__['func'](args)

recursive lambda-expressions possible?

I'm trying to write a lambda-expression that calls itself, but i can't seem to find any syntax for that, or even if it's possible.
Essentially what I wanted to transfer the following function into the following lambda expression: (I realize it's a silly application, it just adds, but I'm exploring what I can do with lambda-expressions in python)
def add(a, b):
if a <= 0:
return b
else:
return 1 + add(a - 1, b)
add = lambda a, b: [1 + add(a-1, b), b][a <= 0]
but calling the lambda form of add results in a runtime error because the maximum recursion depth is reached. Is it even possible to do this in python? Or am I just making some stupid mistake? Oh, I'm using python3.0, but I don't think that should matter?
Maybe you need a Y combinator?
Edit - make that a Z combinator (I hadn't realized that Y combinators are more for call-by-name)
Using the definition of the Z combinator from Wikipedia
>>> Z = lambda f: (lambda x: f(lambda *args: x(x)(*args)))(lambda x: f(lambda *args: x(x)(*args)))
Using this, you can then define add as a completely anonymous function (ie. no reference to its name in its definition)
>>> add = Z(lambda f: lambda a, b: b if a <= 0 else 1 + f(a - 1, b))
>>> add(1, 1)
2
>>> add(1, 5)
6
Perhaps you should try the Z combinator, where this example is from:
>>> Z = lambda f: (lambda x: f(lambda *args: x(x)(*args)))(lambda x: f(lambda *args: x(x)(*args)))
>>> fact = lambda f: lambda x: 1 if x == 0 else x * f(x-1)
>>> Z(fact)(5)
120
First of all recursive lambda expressions are completely unnecessary. As you yourself point out, for the lambda expression to call itself, it needs to have a name. But lambda expressions is nothing else than anonymous functions. So if you give the lambda expression a name, it's no longer a lambda expression, but a function.
Hence, using a lambda expression is useless, and will only confuse people. So create it with a def instead.
But yes, as you yourself discovered, lambda expressions can be recursive. Your own example is. It's in fact so fantastically recursive that you exceed the maximum recursion depth. So it's recursive alright. Your problem is that you always call add in the expression, so the recursion never stops. Don't do that. Your expression can be expressed like this instead:
add = lambda a, b: a > 0 and (1 + add(a-1, b)) or b
Which takes care of that problem. However, your first def is the correct way of doing it.
add = lambda a, b: b if a <= 0 else 1 + add(a - 1, b)
You want the Y combinator, or some other fixed point combinator.
Here's an example implementation as a Python lambda expression:
Y = lambda g: (lambda f: g(lambda arg: f(f)(arg))) (lambda f: g(lambda arg: f(f)(arg)))
Use it like so:
factorial = Y(lambda f: (lambda num: num and num * f(num - 1) or 1))
That is, you pass into Y() a single-argument function (or lambda), which receives as its argument a recursive version of itself. So the function doesn't need to know its own name, since it gets a reference to itself instead.
Note that this does get tricky for your add() function because the Y combinator only supports passing a single argument. You can get more arguments by currying -- but I'll leave that as an exercise for the reader. :-)
a little late ... but I just found this gem # http://metapython.blogspot.com/2010/11/recursive-lambda-functions.html
def myself (*args, **kw):
caller_frame = currentframe(1)
code = caller_frame.f_code
return FunctionType(code, caller_frame.f_globals)(*args,**kw)
print "5! = "
print (lambda x:1 if n <= 1 else myself(n-1)*n)(5)

Categories