print using Lambda function in python 3 - python-3.x

I have the following lists:
para = ['bodyPart', 'shotQuality', 'defPressure', 'numDefPlayers', 'numAttPlayers', 'shotdist', 'angle', 'chanceRating', 'type']
value = [ 0.09786083, 2.30523761, -0.05875112,
0.07905136, -0.1663424 ,-0.73930942, -0.10385882, 0.98845481, 0.13175622]
I want to print using lambda function.
what i want to show is as follow:
coefficient for
bodyPart is 0.09786083
shotQuality is 2.30523761
defPressure is -0.05875112
numDefPlayers is 0.07905136 and so on
I use the following code:
b = lambda x:print(para[x],'is',coeff[x])
print('Coefficient for')
print(b)
and it does not work and only shows this:
Coefficient for
<function <lambda> at 0x000001A8A62A0378>
how can i use lambda function to print to show such output.
thanks
Zep

Lambda function is a function, so you need to use parentheses after the function name to actually call it, just like any other function:
for i in range(len(para)):
print(b(i))
But for the purpose of printing output it's better to use a regular function instead of a lambda function, which is meant for quick expressions rather than functions that do work and return None.

For debugging purposes it can be interesting to print from a lambda function.
You can use a list, tuple or dict to do just that:
Suppose you have lambda function containing a simple test:
lambda x: x > 10
You can then rewrite to print the incoming variable:
lambda x: [print(x), x > 10][-1]
We can now test:
mylambda = lambda x: [print(x), x > 10][-1]
mylambda(12), mylambda(8)
Which yields:
12
8
(True, False)

Related

Lambda functions with multiple conditions

Consider the following code snippet.
## Heading ##
def pos(l):
count_positive=0
for i in l:
if i>0:
count_positive+=1
return count_positive
def even(l):
count_even=0
for i in l:
if i%2==0:
count_even+=1
return count_even
list_int=[[2,-3,-6,10],[10,34,26,87],[1,-2,-3,4]]
list_int=sorted(list_int,key=lambda x: (pos(x),even(x)))
print(list_int)
Lambda functions can't have more than one expression.
But in the code above, I am trying to sort the 2D list first based on number of positive elements and then based on number of even elements. Doesn't this mean that there are two expressions in the lambda function? Or is it like, as I have enclosed the two conditions inside a tuple, it would be considered as one single condition?
Doesn't this mean that there are two expressions in the lambda function?
Yes, there's two expressions, but there's only one expression being returned. When you do
lambda x: (pos(x), even(x))
you're creating a lambda that returns a single value: a tuple with two elements. You can see this by doing
f = lambda x: (pos(x), even(x))
print(f([1, 2, 3, 4])) # Outputs (4, 2)
print(f([-1, -2, -3, -4])) # Outputs (0, 2)
Since it returns a tuple, when you use this as your sorted key, it compares using tuple comparison.
About lambdas, Python documentation says
[Lambdas] are syntactically restricted to a single expression.
It means that you can't do
f = lambda x: pos(x), even(x)
# It'll be parsed as f = ((lambda x: pos(x)), (even(x)))
f = lambda x: return pos(x); return even(x)
# It'll throw a SyntaxError
Or is it like, as I have enclosed the two conditions inside a tuple, it would be considered as one single condition?
No, because this doesn't make sense. A single condition would only be considered if you connect them explicitely with a operator, such as addition:
f = lambda x: pos(x) + even(x)
# Sorts the lists based on the sum of the count of the positive
# numbers with the count of the even numbers
You have one expression - a tuple that calls two functions to get its values. A single "expression" can call multiple functions.
What "Lambda functions can't have more than one expression" means if that you can't have multiple "lines of code" within a lambda, meaning you can't do something like:
lambda x: print(x) return x+1

How to bind parameters to a function without calling it

Let's say I have the following function:
def add(x, y):
return x+y
I would like to bind x=2 and y=2 to the function but not actually call it. What is the correct way to do this? I've done this sometimes with add_bound=lambda: add(2,3), but I'm wondering if this is the 'pythonic' approach or there is another way to do it (perhaps binding certain arguments, and then passing other arguments later.
Often this will be done with a decorator. Here is a general example:
add = lambda x,y: x+y
def wrap(outer_func, *outer_args, **outer_kwargs):
def inner_func(*inner_args, **inner_kwargs):
args = list(outer_args) + list(inner_args)
kwargs = {**outer_kwargs, **inner_kwargs}
return outer_func(*args, **kwargs)
return inner_func
In this case you can do things such as the following:
# pass both at once
>>> x=wrap(add,2,3)
>>> x()
5
# pass one at binding, second at call
>>> x=wrap(add,2)
>>> x(3)
5
# pass both when called
>>> x=wrap(add)
>>> x(2,3)
5
Note that the above is very similar to functools.partial:
The partial() is used for partial function application which “freezes” some portion of a function’s arguments and/or keywords resulting in a new object with a simplified signature. For example, partial() can be used to create a callable that behaves like the int() function where the base argument defaults to two:
from functools import partial
basetwo = partial(int, base=2)
basetwo.__doc__ = 'Convert base 2 string to an int.'
basetwo('10010')
18
def add(x=2, y=2):
return x+y

Please help me understand this python code line by line. I'm facing problem in understanding the flow of data in this code

def myfunc(z):
return lambda x:x+1
t=myfunc(1)
print(t(2))
#I'm facing problem in understanding the flow of data in this code.
A simplified explanation:
your definiton:
def myfunc(z):
return lambda x:x+1
t=myfunc(1)
print(t(2))
Is the same as (since you do not use z anywhere):
def myfunc():
return lambda x:x+1
t=myfunc()
print(t(2))
which is equivalent to:
t = lambda x:x+1
print(t(2))
which is equivalent to:
def t(x):
return x+1
print(t(2))
and what it does, you assign the result of myfunc, which is a lambda (another function definition) to variable t
then you execute t with parameter x set to 2
which evaluates to 2+1 and returns 3

How to make timeit.Timer() work with output of itertools.starmap()

I am having a hard time wrapping my head around
why i can make timeit.Timer() work with output from
functools.partial() but not with output from itertools.starmap().
What I basically need is starmap(func, tuples) to have the same 'attributes' as partial(func, one_arg_only)
but be more generally in the sense that I can actually pass into func multiple arguments at the same time.
What's the easiest workaround here ?
I tried timeit.Timer(starmap(func,tuples)) and obviously get the notorious error:
ValueError: stmt is neither a string nor callable
I presume this is coz starmap's output is not callable. But how do I work around this ?
The itertools.starmap() function returns an itertools.starmap iterable type whereas functools.partial() returns a functools.partial callable type. timeit.Timer() expects the first argument to be a callable (or a string it can exec()).
>>> type(itertools.starmap(lambda *args: list(args), [(1, 2)])
itertools.starmap
>>> type(functools.partial(lambda x: x+1, 1))
functools.partial
What you want to do is create a callable that will exhaust the iterable returned by itertools.starmap. One way to do this would be to call the list() function on the output of the starmap:
# This is the function to call
>>> example_func = lambda *args: len(args)
# This is the iterable that can call the example_func
>>> func_callers = itertools.starmap(example_func, [(1, 2)])
# This is the callable that actually processes func_callers
>>> execute_callers = lambda: list(func_callers)
# And finally using the timer
>>> timeit.Timer(execute_callers)

Why does assigning lambdas not work as expected in Python 3.5?

I know Python is supposed to have first class functions, and I've written some Python which "confirms" that, but the following explodes (runs out of stack depth) my IDLE in 3.5:
k = lambda x:x+1
k = lambda x:k (x+1)
k(0)
Shouldn't it evaluate to 2?
k = lambda x:x+1
j = lambda x:k (x+1)
j(0)
certainly does.
Visualize with lambda
A little printing may help to understand what is going on:
k = lambda x: x+1
print('before:', id(k))
k = lambda x: print('in :', id(k))
k(0)
print('after :', id(k))
before: 4428659024
in : 4428658208
after : 4428658208
The id of the last lambda is the same as the one use inside it. This nicely demonstrates the late binding.
Translate into function statements
Things might a bit clearer if you translate the lambdas into function define with def:
def k(x):
return x + 1
def k(x):
return k(x+1)
k(0)
It is pretty clear that the first definition does make sense as it is overridden by the second one.
In addition, even you use different names for the functions and re-assign the function name:
def k(x):
return x + 1
def j(x):
return k(x+1)
k = j
it appears to be clearer that the first function definition doesn't make sense because the function can never be reached.
The name lookup of k is done at runtime, which means that the function calls itself an infinite number of times (and that the first line does nothing useful). If you want the result you expect then you will have to use the ternary operator to return immediately instead of recursing.

Resources