Python lambda used as an argument, calling other arguments from parent function - python

I'm new to programming and am having a little trouble understanding the lambda function in Python. I understand why it's used and its effectiveness. Just having trouble learning to apply it. I've read a guide and watched a lecture on using lambda as an argument. I've tried using the map function. Not sure if that's the correct approach, but this is my broken code in its most basic form:
def Coord(x, y, z=lambda: z*2 if z < x or z < y else z)):
print(z)
Coord(10,20,30)
Coord(10,20,12)
Coord(10,20,8)
Needs to return 30, 24, and 32, respectively.
Working code without using lambda:
def Coord(x, y, z):
while z < x or z < y:
z*=2
print(z)

You cannot use other parameters from the Coord function in your default parameter definition for z (which is a lambda function in your case).
You may want to do something like this:
def Coord(x, y, w, z=lambda a,b,c: c*2 if c < a or c < b else c):
print(z(x,y,w))
or
def Coord(x, y, w):
z=lambda: w*2 if w < x or w < y else w
print(z())
Both definitions are equivalent when evaluating them with 3 arguments, and they result in:
>>> Coord(10,20,30)
30
>>> Coord(10,20,12)
24
>>> Coord(10,20,8)
16

Related

How to read and break down complex lambda equations in python

This question below is from a past year NUS exam paper, and im not sure how to go about solving this; how do you break down the lambda parts and figure out which bracket is for which lambda variable? I'm unable to trace the code to get 120
def combinator(y):
return (lambda x: lambda y: x(y))(lambda x:y)
combinator(lambda x:x*10)(11)(12)
Ive tried to google but the lambda tutorials are mostly basic so im not sure how to read and break down more complex lambda codes and higher order functions
The function is
def combinator(y):
return (lambda x: lambda y: x(y))(lambda x:y)
combinator(lambda x:x*10)(11)(12)
Let's try to simplify the function. First, take note that you can change the symbol for a function. For example, lambda x: x can be changed to lambda z: z.
As there are a lot of x and y, we will change the symbols to reduce the confusion.
def combinator(y):
return (lambda w: lambda z: w(z))(lambda x:y)
combinator(lambda x:x*10)(11)(12)
Let's try to define the function as mathematics function to make it easier to understand. Let's set
f represents lambda x:x*10, so f(x) = x*10
g represents lambda x:y, so g(x) = y
h represents lambda z:w(z), so h(z) = w(z) => h = w
k represents lambda w: lambda z: w(z), so k(w) = h = w
With the mathematics function defined, you can substitute them back to the function.
combinator(y)
= (lambda w: lambda z: w(z))(lambda x:y)
= k(g)
= g
Therefore, we know that combinator(y) = g
combinator(y)(x) = g(x) = y
combinator(y)(x)(z) = y(z)
Therefore
combinator(lambda x:x*10)(11)(12)
= combinator(f)(11)(12)
= f(12)
= 12*10
= 120

Function as argument for another function

The first function adds two numbers, the second function adds them twice. What is the purpose of Z? I get that x and y are the numbers you're adding together. But what is Z?
def add(x, y):
return x + y
def twice(z, x, y):
return z(z(x, y), z(x, y))
a = 5
b = 10
print(twice(add, a, b))
z represents the function that you want to execute twice. In your example:
twice(add, a, b)
twice received three arguments, add, a, and b. add is a reference to the add function, and becomes z instead the twice function. You might imagine a scenario in which you pass a different hypothetical function subtract to twice.
In twice(z, x, y), z is a function. So when you call twice(add, a, b), z is the function add. Therefore return z(z(x, y), z(x, y)) would be
return add(add(a, b), add(a, b))
So it calculates (a + b) + (a + b).
If you pass, for example, a function sub = lambda x, y: x - y, then twice(sub, a, b) will return sub(sub(a, b), sub(a, b)) instead, i.e., (a - b) - (a - b).
Another example:
print(twice(lambda x, y: x + ' ' + y, 'hello', 'world'))
# hello world hello world

'NoneType' object is not iterable - where is an error?

My aim is to take a triple (A, B, C), compute three "neighbours", and then output the maximum of each of those neighbours to a list.
For example, the neighbours of (sqrt(6), 4*sqrt(3), 9*sqrt(2)) are
(sqrt(3)*sqrt(2), 3*sqrt(2), 4*sqrt(3))
(4*sqrt(3), 35*sqrt(3)*sqrt(2), 9*sqrt(2))
(sqrt(3)*sqrt(2), 9*sqrt(2), 14*sqrt(3))
so the values 14*sqrt(3), 36*sqrt(6), 4*sqrt(3) would be the output.
When I try this:
A = 1*sqrt(6)
B = 4*sqrt(3)
C = 9*sqrt(2)
def nbhs_1(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((X.canonicalize_radical(), (X * Y - Z).canonicalize_radical(), Y.canonicalize_radical()))
def nbhs_2(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((Y.canonicalize_radical(), (Y * Z - X).canonicalize_radical(), Z.canonicalize_radical()))
def nbhs_3(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((X.canonicalize_radical(), Z.canonicalize_radical(), (X * Z - Y).canonicalize_radical()))
result_1 = nbhs_1((A, B, C))
result_2 = nbhs_2((A, B, C))
result_3 = nbhs_3((A, B, C))
print(result_1)
print(result_2)
print(result_3)
l = [max(result_1), max(result_2), max(result_3)]
I get 'NoneType' object is not iterable.
The main problem is that you are not structuring the function properly:
It is recommended that you expose your arguments within the function call. Don't def nbhs_1(triple), do instead def nbhs_1(X, Y, Z). In this way you can actually have one single function that does what you want (easier to maintain)
Return your result. At the moment you are printing the outcome of the function call but you are not returning those results.
I'm also not sure the canonicalize_radical() call is also done properly. Python is object-oriented and by writing var.canonicalize_radical() you are inferring that var should itself know about this function (e.g. the function is part of var) but that sounds wrong. The correct call may be canonicalize_radical(var)
Basically, this should be closer to a correct solution:
A=1*sqrt(6)
B=4*sqrt(3)
C=9*sqrt(2)
def nbhs(X, Y, Z):
out1 = canonicalize_radical(X)
out2 = canonicalize_radical(X*Y-Z)
out3 = canonicalize_radical(Y)
return out1, out2, out3
l = [max(nbhs(A, B, C)), max(nbhs(B, A, C)), max(nbhs(C, B, A))]
The problem is that you are not calling the functions nbhs_1, nbhs_2, and nbhs_3 and also the functions aren't returning any values
from math import sqrt
A=1*sqrt(6)
B=4*sqrt(3)
C=9*sqrt(2)
triple = (A, B, C)
def nbhs_1(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (X.canonicalize_radical(),(X*Y-Z).canonicalize_radical(),Y.canonicalize_radical())
def nbhs_2(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (Y.canonicalize_radical(),(Y*Z-X).canonicalize_radical(),Z.canonicalize_radical())
def nbhs_3(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (X.canonicalize_radical(),Z.canonicalize_radical(),(X*Z-Y).canonicalize_radical())
l=[max(nbhs_1(triple)),max(nbhs_2(triple)),max(nbhs_3(triple))]

How can make a axiom in Z3Py correctly?

I am working in this axiom ForAll X( f(x) > 0 -> b == True) .
How I could to do it in Z3Py? I try to do this:
from z3 import *
Z = IntSort()
f = Function('f', Z, Z)
g = Function('g', Z, Z)
a, n, x = Ints('a n x')
b = BoolSort()
solve(ForAll(x,Implies(f(x) > 0,b ==True)))
but Python return me AttributeError: 'bool' object has no attribute 'ast'
You can declare b as b = Bool('b'). Then it works.
By the way, you can replace b == True by just b as in
solve(ForAll(x,Implies(f(x) > 0, b ))).
BoolSort etc. are meant for parameters to Z3Py functions, not for variables.
What's your axiom trying to state? Note that in the formula ForAll X. (f(x) > 0 -> b == True), b is a free variable. So, this doesn't really seem to correspond to anything logical. But, if that's what you really want to say, this is how you'd code it:
from z3 import *
Z = IntSort()
f = Function('f', Z, Z)
g = Function('g', Z, Z)
a, n, x = Ints('a n x')
b = Bool('b')
solve(ForAll(x,Implies(f(x) > 0, b)))
And we get:
$ python a.py
[b = False, f = [else -> 0]]
What's z3 telling us? It says, OK, I'll pick f to be a function that maps everything to 0. So, your implication will have a antecedent 0 > 0, which is always false, and thus the implication is always true. (False implies anything.) The choice for False for b in the model is really irrelevant.
So, z3 did find you a model for f and b that satisfied your quantified assertion. Just like you asked. But I suspect this wasn't really the formula you were trying to assert. Axioms are typically closed: That is, they have no free variables, other than the uninterpreted functions symbols they include. Of course, this all depends on what exactly you're trying to do.

python futures and tuple unpacking

What is an elagant/idiomatic way to achieve something like tuple unpacking with futures?
I have code like
a, b, c = f(x)
y = g(a, b)
z = h(y, c)
and I would like to convert it to use futures.
Ideally I would like to write something like
a, b, c = ex.submit(f, x)
y = ex.submit(g, a, b)
z = ex.submit(h, y, c)
The first line of that throws
TypeError: 'Future' object is not iterable
though.
How can I get a,b,c without having to make 3 additional ex.submit calls? ie. I would like to avoid having to write this as:
import operator as op
fut = ex.submit(f, x)
a = client.submit(op.getitem, fut, 0)
b = client.submit(op.getitem, fut, i)
c = client.submit(op.getitem, fut, 2)
y = ex.submit(g, a, b)
z = ex.submit(h, y, c)
I guess a potential solution is to write an unpack function like below,
import operator as op
def unpack(fut, n):
return [client.submit(op.getitem, fut, i) for i in range(n)]
a, b, c = unpack(ex.submit(f, x), 3)
y = ex.submit(g, a, b)
z = ex.submit(h, y, c)
which works: for example if you first define:
def f(x):
return range(x, x+3)
x = 5
g = op.add
h = op.mul
then you get
z.result() #===> 77
I thought something like this might already exist.
The above only works with dask.distributed.Future. It does not work for plain concurrent.futures.Future.
A quick glance at:
https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Future
suggests that you'll have to do something like
afuture = ex.submit(f, x)
a,b,c = afuture.result()
...
submit returns a Future object, not the result of running f(x).
This SO answer indicates that chaining futures is not trivial:
How to chain futures in a non-blocking manner? That is, how to use one future as an input in another future without blocking?

Categories

Resources