Is there a way to do the following in just one line with lambdas in python?
squared = lambda x : x**2
cubed = lambda x : x**3
squareCubed = lambda x : squared(cubed(x))
without using any helper functions or reduce.
print(squareCubed(2)) # > 64
Sure, you can do something like:
squareCube = (lambda f, g: lambda x: f(g(x)))(lambda x: x**2, lambda x: x**3)
But why do this?
In any case, you shouldn't be assigning the result of lambda to a variable if you are following the official PEP8 style guide. What is wrong with:
def square(x):
return x**2
def cube(x):
return x**3
def compose(f, g):
return lambda x: f(g(x))
square_cube = compose(square, cube)
Is much more readable.
If you want to hard code it:
squareCube = lambda x: (x**3)**2
But generically:
compose = lambda f, g: lambda x: f(g(x))
squareCube = compose(lambda x: x**2, lambda x: x**3)
Or, in one line:
squareCube = (lambda f, g: lambda x: f(g(x)))(lambda x: x**2, lambda x: x**3)
squareCubed = lambda x : (x**3)**2
print(squareCubed(2)) # gives 64
Related
This works:
C = df_temp['For Team'].map(
lambda x: df_teams.loc[df_teams['CommentName']==x,'TeamColor'].item())
But I would like to add a condition to lambda of x being in another list 'y', like so:
y = ['salah', 'zico', 'pele']
I've tried:
lambda x: df_teams.loc[df_teams['CommentName']==x if x in y,'TeamColor'].item())
But this raises invalid syntax.
How do I do this?
Let us try isin
df_teams.loc[df_teams['CommentName'].isin(y),'TeamColor'].item()
You can always create a named function first and, then, apply that on lambdas.
y = ["salah", "zico", "pele"]
def get_teamcolor(x, y):
if x in y:
return df_teams.loc[df_teams["CommentName"] == x, "TeamColor"].item()
C = df_temp["For Team"].map(lambda x: get_teamcolor(x, y))
This should work:
C = df_temp['For Team'].map(lambda x: df_teams.loc[df_teams['CommentName']==x and x in y,'TeamColor'].item())
You need to join both conditions with an "and" instead of adding an if statement.
I need to convert the following code involving several lambda functions into separate "regular" functions. How would I do this?
I'm working on Pyspark right now. Data source is an RDD
result = rdd.filter(lambda x: x[0]=='9439').map(lambda x: (x[0], json.loads(x[1])['exposures'])).flatMapValues(lambda x: x).map(lambda x: {'serial_no' : x[0], **x[1]})
My attempt:
def acct_tuple(x):
return (x[0], json.loads(x[1])['exposures'])
def flat_map(x):
return x
def get_tuple(x):
return {'serial_no': x[0], **x[1]}
rdd = rdd.map(acct_tuple(x)).flatMapValues(flat_map(x)).map(get_tuple(x))
is there a better way to do this?
You should pass the function itself as a parameter, and do not call it, hence:
def acct_tuple(x):
return (x[0], json.loads(x[1])['exposures'])
def flat_map(x):
return x
def get_tuple(x):
return {'serial_no': x[0], **x[1]}
rdd = rdd.map(acct_tuple).flatMapValues(flat_map).map(get_tuple)
I'm wondering why these 2 pieces of code are different?
This code gives me the answer of 5
curry2 = lambda f: lambda x: lambda y: f(x, y)
m = curry2(add)
m(2)(3)
5
This one gives me the location of my function
def lambda_curry2(func):
return lambda f: lambda x: lambda y: f(x, y)
curry2 = lambda_curry2(add)
add_three = curry2(3)
add_three(5)
The second one isn't using func. You don't need as many lambdas, because func is the function you want to call.
So it should be;
def lambda_curry2(func):
return lambda x: lambda y: func(x, y)
Put another way, your definition of curry2 is equivalent to:
def curry2(f):
return lambda x: lambda y: f(x, y)
In general,
name = lambda <vars>: <expression>
is short for
def name(<vars>):
return <expression>
lambda is usually used when you don't need to name the function (e.g. when you want to pass a simple function as an argument or return it as a value).
I am trying to understand nested lambdas:
f = lambda x, y: y(y(x))
g = lambda x : lambda y: x(y)
print( f(lambda x: x+1, g) (4) )
I was told that this code printed "5". How is this explained, and how should one parse the (4) in the last line?
From my understanding of lambda, if,
h = lambda a, b : a+b
i know that print(h(1,2)) will give 3
as a = 1, b =2, and proceed with a+b = 1+2 =3
f(lambda x: x+1, g) ultimately returns another function. That function is then called with 4 as its argument to produce the final result of 5.
Let h = lambda x: x + 1, because this becomes a mess to trace otherwise.
First, we apply f to h and g.
f(h, g)(4) == (lambda x,y: y(y(x))(h, g)(4)
== g(g(h))(4)
Next, we'll evaluate the inner call to g:
g(g(h))(4) == g((lambda x: lambda y: x(y))(h))(4)
== g(lambda y: h(y))(4)
== g(h)(4)
The last step is an example of eta reduction, to use a term from lambda calculus: a function that applies a second function to an argument is equivalent to the second function itself.
Finally, we evaluate g(h) again the same way, which finally gets us to an expression that doesn't involve passing a function as an argument, and lets us get a final answer.
g(h)(4) == (lambda y: h(y))(4)
== h(4)
== (lambda x: x + 1)(4)
== 4 + 1
== 5
Let's have a go at expanding the logic. First, I'm going to rename some argument names to differentiate your two functions:
f = lambda i, j: j(j(i))
g = lambda x: lambda y: x(y)
Now f(lambda x: x+1, g) is equivalent to:
h = (lambda i, j: j(j(i)))(lambda x: x+1, g)
Here, a function being used as an argument. This is fine, as functions are first-class objects in Python and can be passed around in this way. So evaluating this:
h = g(g(lambda x: x+1))
But g is nothing fancy, it simply takes a function and applies it to an argument. It can be considered an "identity" function with a function as an argument. You can get rid of g altogether. So we have:
h = (lambda x: x+1)
In other words, h just adds one to any input.
h = lambda x: x+1 is a function that returns 1 more than the value passed to it. It is equivalent to:
def h(x):
return x+1
f = lambda x, y: y(y(x)) is a function which takes a value and a function as a pair of arguments and evaluates function(function(value)).
It is equivalent to:
def f(x, y):
return y(y(x))
g = lambda x: lambda y: x(y) is a decorator function that returns a new function based on function passed to it.It is equivalent to:
def g(x):
def new_func(y):
return x(y)
return new_func
the given lambda expressions,
f = lambda x, y: y(y(x))
g = lambda x : lambda y: x(y)
expression to evaluate
f(lambda x: x+1, g) (4)
this reduces to
=> g(g(lambda x: x+1)) (4)
now note that g(g(lambda x: x+1)) returns a function g(lambda x: x+1)
=> g(lambda x: x+1) (4)
now here g(lambda x: x+1) again returns a function (x+1)
=> (x+1) (4)
this evaluates to 4+1 i.e 5
=> 5
When assigning a variable to an anonymous function using a one line if statement, the 'else' case does not behave as expected. Instead of assigning the anonymous function listed after the 'else', a different anonymous function is assigned. This function returns the expected anonymous function.
>> fn = lambda x: x if True else lambda x: x*x
>> fn(2)
2
>> fn = lambda x: x if False else lambda x: x*x
>> fn(2)
<function <lambda> at 0x10086dc08>
>> fn('foo')(2)
4
What seems to be happening is that lambda x: x if False else lambda x: x*x as a whole is returned as an anonymous function in the 'else' case. I was able to achieve the desired behavior by using the following:
>> fn = (lambda x: x*x, lambda x: x)[True]
>> fn(2)
2
>> fn = (lambda x: x*x, lambda x: x)[False]
>> fn(2)
4
However, I would still like to get the bottom of this unusual behavior. Any thoughts?
lambda has a weaker binding than the conditional expression. In fact, it has the least operator precedence in the language. From the documentation1:
So, this line:
fn = lambda x: x if True else lambda x: x*x
is actually being interpreted by Python as:
fn = lambda x: (x if True else lambda x: x*x)
To do what you want, you would need to add parenthesis:
fn = (lambda x: x) if True else (lambda x: x*x)
1Note that the table is ordered from least to greatest.