I have been looking for ways to assign a or statement to a variable, in a way that the variable can be used as a reference for other comparisons.
What i'm trying to accomplish by example:
a = 1
b = 0
c = a or b
print(a == c) #would return True
print(b == c) #would also return True
What you seem to want is somewhat close to the way sets work, with the operator | replacing or (which cannot be overridden):
a = {0}
b = {1}
c = a | b # or a.union(b)
a.issubset(c) # True
b.issubset(c) # True
{3}.issubset(c) # False
You could in principle make your own class that extends set:
class Singleton(set):
def __init__(self, n):
super().__init__([n])
def __eq__(self, other):
return self.issubset(other) or other.issubset(self)
a = Singleton(1)
b = Singleton(0)
c = a | b
print(a == c) # True
print(b == c) # True
But it is doubtful whether the confusing code this generates would ever be worth it.
You can change the definition of the == operator by creating a class and replacing your integer values with objects that contain each integer, so you will be able to override the equal operator with the __eq__ function. In this example, I will negate the result of the default operator to show you that you can apply whatever definition you need for that operation. The only disadvantage is that in Python, you can't override or redefine or:
class num:
def __init__(self, n):
self.n = n
def __eq__(self, n):
return not n==self.n
a = num(1)
b = num(0)
c = a or b
print(a == c)
print(b == c)
You can get something like that by using functools.partial and operator.or_:
a=True
b=False
c = partial(or_, a,b)
c()
True
But beware, a and b are evaluated at definition time:
a=False
c()
True
Consider a function getf taking a numpy array a and integer b. I want to return a callable function f such that f has value 0 for a< b and a>b and value 1 for a=b.
Something like
getf(a,b):
if a< b & b>a:
return 0
else:
return 1
does not work.
How do I can ensure that my return value is a function?
Example
a = [1,2,3,4,5]
b=2
return function with result array [0,1,0,0,0]
I don't understand why you need this, but this code defines a function and returns it, which can be called with two keyword arguments.
def getf():
def f(a, b):
return [int(b==i) for i in a]
return f
print(getf()(a = [1,2,3,4,5], b=2))
You need to use vectorial code, not return a scalar. Also, use a numpy array for a.
Finally, your conditions were incorrect (you had twice the same condition). I imagine you want to check if a is greater of equal b and lower or equal b (which is a == b, but let's keep it like this for the sake of the example).
def getf(a,b):
return ((a >= b) & (b >= a)).astype(int)
a = np.array([1,2,3,4,5])
b = 2
getf(a, b)
# array([0, 1, 0, 0, 0])
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 *
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.
I have multiple expensive functions that return results. I want to return a tuple of the results of all the checks if all the checks succeed. However, if one check fails I don't want to call the later checks, like the short-circuiting behavior of and. I could nest if statements, but that will get out of hand if there are a lot of checks. How can I get the short-circuit behavior of and while also storing the results for later use?
def check_a():
# do something and return the result,
# for simplicity, just make it "A"
return "A"
def check_b():
# do something and return the result,
# for simplicity, just make it "B"
return "B"
...
This doesn't short-circuit:
a = check_a()
b = check_b()
c = check_c()
if a and b and c:
return a, b, c
This is messy if there are many checks:
if a:
b = check_b()
if b:
c = check_c()
if c:
return a, b, c
Is there a shorter way to do this?
Just use a plain old for loop:
results = {}
for function in [check_a, check_b, ...]:
results[function.__name__] = result = function()
if not result:
break
The results will be a mapping of the function name to their return values, and you can do what you want with the values after the loop breaks.
Use an else clause on the for loop if you want special handling for the case where all of the functions have returned truthy results.
Write a function that takes an iterable of functions to run. Call each one and append the result to a list, or return None if the result is False. Either the function will stop calling further checks after one fails, or it will return the results of all the checks.
def all_or_none(checks, *args, **kwargs):
out = []
for check in checks:
rv = check(*args, **kwargs)
if not rv:
return None
out.append(rv)
return out
rv = all_or_none((check_a, check_b, check_c))
# rv is a list if all checks passed, otherwise None
if rv is not None:
return rv
def check_a(obj):
...
def check_b(obj):
...
# pass arguments to each check, useful for writing reusable checks
rv = all_or_none((check_a, check_b), obj=my_object)
In other languages that did have assignments as expressions you would be able to use
if (a = check_a()) and (b = check_b()) and (c = check_c()):
but Python is no such language. Still, we can circumvent the restriction and emulate that behaviour:
result = []
def put(value):
result.append(value)
return value
if put(check_a()) and put(check_b()) and put(check_c()):
# if you need them as variables, you could do
# (a, b, c) = result
# but you just want
return tuple(result)
This might loosen the connection between the variables and function calls a bit too much, so if you want to do lots of separate things with the variables, instead of using the result elements in the order they were put in the list, I would rather avoid this approach. Still, it might be quicker and shorter than some loop.
You could use either a list or an OrderedDict, using a for loop would serve the purpose of emulating short circuiting.
from collections import OrderedDict
def check_a():
return "A"
def check_b():
return "B"
def check_c():
return "C"
def check_d():
return False
def method1(*args):
results = []
for i, f in enumerate(args):
value = f()
results.append(value)
if not value:
return None
return results
def method2(*args):
results = OrderedDict()
for f in args:
results[f.__name__] = result = f()
if not result:
return None
return results
# Case 1, it should return check_a, check_b, check_c
for m in [method1, method2]:
print(m(check_a, check_b, check_c))
# Case 1, it should return None
for m in [method1, method2]:
print(m(check_a, check_b, check_d, check_c))
There are lots of ways to do this! Here's another.
You can use a generator expression to defer the execution of the functions. Then you can use itertools.takewhile to implement the short-circuiting logic by consuming items from the generator until one of them is false.
from itertools import takewhile
functions = (check_a, check_b, check_c)
generator = (f() for f in functions)
results = tuple(takewhile(bool, generator))
if len(results) == len(functions):
return results
Another way to tackle this is using a generator, since generators use lazy evaluation. First put all checks into a generator:
def checks():
yield check_a()
yield check_b()
yield check_c()
Now you could force evaluation of everything by converting it to a list:
list(checks())
But the standard all function does proper short cut evaluation on the iterator returned from checks(), and returns whether all elements are truthy:
all(checks())
Last, if you want the results of succeeding checks up to the failure you can use itertools.takewhile to take the first run of truthy values only. Since the result of takewhile is lazy itself you'll need to convert it to a list to see the result in a REPL:
from itertools import takewhile
takewhile(lambda x: x, checks())
list(takewhile(lambda x: x, checks()))
main logic:
results = list(takewhile(lambda x: x, map(lambda x: x(), function_list)))
if len(results) == len(function_list):
return results
you can learn a lot about collection transformations if you look at all methods of an api like http://www.scala-lang.org/api/2.11.7/#scala.collection.immutable.List and search/implement python equivalents
logic with setup and alternatives:
import sys
if sys.version_info.major == 2:
from collections import imap
map = imap
def test(bool):
def inner():
print(bool)
return bool
return inner
def function_for_return():
function_list = [test(True),test(True),test(False),test(True)]
from itertools import takewhile
print("results:")
results = list(takewhile(lambda x:x,map(lambda x:x(),function_list)))
if len(results) == len(function_list):
return results
print(results)
#personally i prefer another syntax:
class Iterator(object):
def __init__(self,iterable):
self.iterator = iter(iterable)
def __next__(self):
return next(self.iterator)
def __iter__(self):
return self
def map(self,f):
return Iterator(map(f,self.iterator))
def takewhile(self,f):
return Iterator(takewhile(f,self.iterator))
print("results2:")
results2 = list(
Iterator(function_list)
.map(lambda x:x())
.takewhile(lambda x:x)
)
print(results2)
print("with additional information")
function_list2 = [(test(True),"a"),(test(True),"b"),(test(False),"c"),(test(True),"d")]
results3 = list(
Iterator(function_list2)
.map(lambda x:(x[0](),x[1]))
.takewhile(lambda x:x[0])
)
print(results3)
function_for_return()
If you don't need to take an arbitrary number of expressions at runtime (possibly wrapped in lambdas), you can expand your code directly into this pattern:
def f ():
try:
return (<a> or jump(),
<b> or jump(),
<c> or jump())
except NonLocalExit:
return None
Where those definitions apply:
class NonLocalExit(Exception):
pass
def jump():
raise NonLocalExit()
Flexible short circuiting is really best done with Exceptions. For a very simple prototype you could even just assert each check result:
try:
a = check_a()
assert a
b = check_b()
assert b
c = check_c()
assert c
return a, b, c
except AssertionException as e:
return None
You should probably raise a custom Exception instead. You could change your check_X functions to raise Exceptions themself, in an arbitrary nested way. Or you could wrap or decorate your check_X functions to raise errors on falsy return values.
In short, exception handling is very flexible and exactly what you are looking for, don't be afraid to use it. If you learned somewhere that exception handling is not to be used for your own flow control, this does not apply to python. Liberal use of exception handling is considered pythonic, as in EAFP.
You mentioned 'short-circuiting' in your answer, which can be done with the 'or' statement. Top answer basically does the same thing, but in case someone wants to know more about this behaviour you could do this;
class Container(object):
def __init__(self):
self.values = []
def check_and_cache(self, value, checking_function):
value_true = checking_function(value)
if value_true:
self.values.append(value)
return True
c = Container()
if not c.check_and_cache(a, check_a) or not c.check_and_cache(b, check_b) or not c.check_and_cache(c, check_c):
print 'done'
return tuple(c.values)
The 'not .. or' setup of the if statements will result in a 'True' if the check fails, so the overall if statement passes without evaluating the remaining values.
Since I can not comment "wim":s answer as guest, I'll just add an extra answer.
Since you want a tuple, you should collect the results in a list and then cast to tuple.
def short_eval(*checks):
result = []
for check in checks:
checked = check()
if not checked:
break
result.append(checked)
return tuple(result)
# Example
wished = short_eval(check_a, check_b, check_c)
You can try use #lazy_function decorator from lazy_python
package. Example of usage:
from lazy import lazy_function, strict
#lazy_function
def check(a, b):
strict(print('Call: {} {}'.format(a, b)))
if a + b > a * b:
return '{}, {}'.format(a, b)
a = check(-1, -2)
b = check(1, 2)
c = check(-1, 2)
print('First condition')
if c and a and b: print('Ok: {}'.format((a, b)))
print('Second condition')
if c and b: print('Ok: {}'.format((c, b)))
# Output:
# First condition
# Call: -1 2
# Call: -1 -2
# Second condition
# Call: 1 2
# Ok: ('-1, 2', '1, 2')
This is similar to Bergi's answer but I think that answer misses the point of wanting separate functions (check_a, check_b, check_c):
list1 = []
def check_a():
condition = True
a = 1
if (condition):
list1.append(a)
print ("checking a")
return True
else:
return False
def check_b():
condition = False
b = 2
if (condition):
list1.append(b)
print ("checking b")
return True
else:
return False
def check_c():
condition = True
c = 3
if (condition):
list1.append(c)
print ("checking c")
return True
else:
return False
if check_a() and check_b() and check_c():
# won't get here
tuple1 = tuple(list1)
print (tuple1)
# output is:
# checking a
# (1,)
Or, if you don't want to use the global list, pass a reference of a local list to each of the functions.
If the main objection is
This is messy if there are many checks:
if a:
b = check_b()
if b:
c = check_c()
if c:
return a, b, c
A fairly nice pattern is to reverse the condition and return early
if not a:
return # None, or some value, or however you want to handle this
b = check_b()
if not b:
return
c = check_c()
if not c:
return
# ok, they were all truthy
return a, b, c