Pass functional arguments through ternary operator in Python - python

This might be a basic question because I am still learning Python. But let's suppose I want to do something like this,
def add(a, b):
return a + b
a, b, c, d = 1, 2, 3, 4
sum = add(a, b if b == 2 else c, d)
Basically, I am trying to pass multiple functional args from inside a ternary operator(and I want a similar solution, if possible). This code currently gives the following error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() takes 2 positional arguments but 3 were given
What else have I tried:
add((a, b) if b == 2 else (c, d))
add(*(a, b) if b == 2 else *(c, d))

>>> add(*((a, b) if b == 2 else (c, d)))
3
As pointed out in the comments, the fact that you need so many parens to do this is a good sign that this is not a good way to structure this code.

what about
add(*(a, b) if b == 9 else (c, d))
It is similar to
add(*((a, b) if b == 9 else (c, d)))

sum_ = add(a, b) if b==2 else add(c, d)
above statement is equivalent to
sum_ = 0
if b==2:
sum_ = add(a, b)
else:
sum_ = add(c, d)
if in confusion, it is better to write a full statement, and then try to make it simple and in Turney.
Also, it's recommended, not to use the inbuilt function for the variable name

the problem is in the fucntion argument ,you declare a fucntion with 2 variable but you pass 3 ,what i inderstand you pass argument to funciton and it return the sum of the argument ,you can do this
def add(*args):
return sum(args)
a, b, c, d = 1, 2, 3, 4
value = add(a, b if b == 2 else c, d)
*don't declare sum as variable it is an an inbuilt function of python *

Related

Defining Functions in Z3Py that return true for some inputs and false for others

I am trying to define a function that will return true if two objects are connected and false otherwise.
In the example (cf. picture), where node a is connected to node b and c but there is no connection between b and c I want the function to behave like that:
connected(a, b) = true
connected(a, c) = true
connected(b, c) = false
So my question can be divided in two sub-questions:
a) How would i define such a function generally with the python api of Z3 (z3py), considering, that i would provide all possible assignments for the function upfront.
b) is it possible to define a funciton in a way, that I only provide the cases, where the function evaluates to true (i.e. only for the connected nodes) and then say somehow, that this function should evaluate to false in all other cases.
Sure:
from z3 import *
Object, (a, b, c) = EnumSort('Object', ('a', 'b', 'c'))
connections = [(a, b), (a, c)]
def isConnected(x, y):
return Or([And(x == i, y == j) for (i, j) in connections])
s = Solver()
s.add(isConnected(a, b))
s.add(isConnected(a, c))
print(s.check())
s.add(isConnected(b, c))
print(s.check())
The first print will say sat, and the second will say unsat, since b and c are not connected.
You can easily generalize this to any number of objects. Or even do things like:
s = Solver()
p = Const('p', Object)
q = Const('q', Object)
s.add(isConnected(p, q))
print(s.check())
print(s.model())
which will print:
sat
[q = b, p = a]
but note that this assignment will never contain the pair b, c as requested.
alias is right, you can simply declare the signature of the function and the implementation as you please. In other words, the evaluation of the function is up to you to assert.

Python declarative loop refactor (need access multiple elements)

Hi I have this piece of code and trying to refactor it to be declarative. But AFAIK, all declarative methods like map() reduce() filter() will loop through each element of the container, not a few like this
def arrayCheck(nums):
# Note: iterate with length-2, so can use i+1 and i+2 in the loop
for i in range(len(nums)-2):
# Check in sets of 3 if we have 1,2,3 in a row
if nums[i]==1 and nums[i+1]==2 and nums[i+2]==3:
return True
return False
So how to write this code, declarative way?
First, you can use a zip to rewrite your loop:
def array_check(nums):
for a, b, c in zip(nums, nums[1:], nums[2:]):
if a == 1 and b == 2 and c == 3:
return True
return False
Then, use the tuple comparison:
def array_check(nums):
for a, b, c in zip(nums, nums[1:], nums[2:]):
if (a, b, c) == (1, 2, 3):
return True
return False
And then the any builtin:
def array_check(nums):
return any((a, b, c) == (1, 2, 3) for a, b, c in zip(nums, nums[1:], nums[2:]))
Test:
>>> array_check([1,3,4,1,2,3,5])
True
>>> array_check([1,3,4,1,3,5])
False
Note: for a faster version, see #juanpa.arrivillaga comment below.
If you want to mimic functional style:
import operator, functools
def array_check(nums):
return any(map(functools.partial(operator.eq, (1,2,3)), zip(nums, nums[1:], nums[2:])))
But that's really unpythonic!

Python: Why does this work?

I'd like some help clarifying the logic behind this.
from operator import add, sub
def a_plus_abs_b(a, b):
if b < 0:
f = sub # subtract a negative value
else:
f = add # add a positive one
return f(a, b)
I originally thought that I would have to think of some complex mathematical expression to allow this function to work, but someone showed me that just adding sub and add to f allows it to work properly. I'm having difficulty trying seeing how this works, so any clarifying remarks would be greatly appreciated.
Well, the logic itself works because a + abs(b) == a + b when b >= 0 and a + abs(b) == a - b when b < 0. I have commented out your code below.
from operator import add, sub
# two functions are imported:
# add(x,y) -> (x + y)
# sub(x,y) -> (x - y)
def a_plus_abs_b(a, b):
# when b < 0, (a + abs(b)) == (a - b)
if b < 0:
# f is a temporary variable holding the function sub
f = sub
# when b >= 0, (a + abs(b)) == (a + b)
else:
# f is a temporary variable holding the function add
f = add
# apply the arguments to the function determined above
return f(a, b)
However, this function could be written in a single line.
def a_plus_abs_b(a, b):
return a + abs(b)
The interesting thing about your function is that it highlights that functions are first-order objects in Python. This means that they can be passed around and assigned to variables and many other things.
sub is just the name of a reference to a function object that implements subtraction. Like any other reference, you can assign its value to another name, so f = sub simply makes f another name for reference stored in sub. As such, f(a, b) and sub(a, b) both call the same underlying function.

Python - if x not in any of a, b, c

In a program I am writing at the moment I need to do the following:
if (x not in a) and (x not in b) and (x not in c):
which, of course, is very tedious, especially when a, b, and c all have much longer names.
Is there a built-in function that can do this:
if x is_in_one_of(a, b, c):
I know how I can do this with a function, and I am just wondering if there is a built-in way to do it.
Thanks in advance
You can do that as:
if all(x not in i for i in (a,b,c)):
The all above will only evaluate to True if x is not in any of a,b, or c
Or in other words:
if not any(x in i for i in (a,b,c)):
You asked for built-in ways of doing it but as you have it is very readable, albeit tedious to type. You could break onto a newline before each 'and'
For example (pep8 compliant)
if x not in a \
and x not in b \
and x not in c:
Alternatively, you could always use concatenation if appropriate
if x not in a + b + c:
Put it in a list
val = [a, b, c, d, e]
if x not in val:
do stuff
also this would work
if x not in [a, b, c]

Python 3.x - Simple function that returns another function

I just recently started programming in Python and I've been trying to create a simple function that takes two parameters, a and b, and returns the result of the sum of a and |b|. I want to return f(a, b) and not just f. I know that I'm assigning f to be an int in my current code and so it returns "int not callable error" when I run. So I have to assign f to be a function of some sort. I'm fairly certain I'm missing something fundamental here, I'm just not sure exactly what. Thanks for any help!
from operator import add, sub
def a_plus_abs_b(a, b):
"""Return a+abs(b), but without calling abs.
>>> a_plus_abs_b(2, 3)
5
>>> a_plus_abs_b(2, -3)
5
"""
if b < 0:
f = sub(a, b)
else:
f = add(a, b)
return f(a, b)
f = sub(a, b)
doesn't create a function it computes the result, so when you're calling f(a, b) you're calling an integer.
To fix it, assign the function in-line with a ternary to select which function to create depending on the sign of b
f = sub if b < 0 else add
Jean-Fançois's answer is great, but if you're not understanding the fundamentals behind this, you should look into another example that uses lambdas:
def returns_function_example():
return lambda arg1: arg1 + 2
function_returned = returns_function_example()
print(function_returned(1))
# Output = 3
Run this in your debugger to see that "function_returned" in indeed a function. You can connect the dots after the "print" function is called.
Functions are first-class citizens in Pythonland, so that you can manipulate them as any other object.
Suppose you create your function:
def add(a, b): return a + b
If you write add, that's a function. But if you write add(2,4), or add(a, b) assuming that a and b are defined, then you are calling the function, so you get a result. These are two completely different things: there is f, a callable, and f(a,b) which returns a value.
So if you write:
>>> f = add
>>> type(f)
<class 'function'>
That's what you want, you now have a function that does exactly what add does (and you could say it actually is add).
By contrast, if you write:
>>> f = add(a,b)
>>> type(f)
<class 'int'>
>>> f
11
That's a value.
So to make a long story short:
from operator import add, sub
def a_plus_abs_b(a, b):
"""
Return a+abs(b), but without calling abs.
>>> a_plus_abs_b(2, 3)
5
>>> a_plus_abs_b(2, -3)
5
"""
if b < 0:
f = sub
else:
f = add
return f(a, b)

Categories

Resources