I know Java and C and I used to use Switch statements, but there aren't in python.
I see many ways of use if-elif-else to remplace, but any that remplace completly.
Example of code that I want remplace.
switch(expression) {
case a:
doA();
case b:
doB();
case c:
doC();
break;
case d:
case e:
doDE()
break;
case f:
case g:
doFG():
case h:
doH();
break;
case i:
doI();
default:
foo();
break;
}
As you can see not all case are follow by break, and there is code between some cases that only executed with one case, but there is also common code that is executed in both case.
I see a many ways, but any that allow this at same time. And I think this is the real diference between if-elif-else, and switch-case.
So there is any way of do this will be great, or it's only posible with repeted functions calls and complex if with all posibilities?.
Thank you.
The switch statement is considered harmful. That's probably why Python doesn't have it. The fallthrough behavior is a major source of bugs in C code. It's easy to forget a break; That's why C# disallows it--you'd have to use an explicit goto instead. It's the same in Python's dict of functions approach. You put in a call to the next function. "Explicit is better than implicit".
The easiest way to make a dict of functions (with identifier keys) is with a class declaration.
class switch:
def a():
print('a')
switch.b()
def b():
print('b')
switch.c()
def c():
print('c')
def d():
switch.e()
def e():
print('de')
def f():
switch.g()
def g():
print('fg')
def h():
print('h')
def i():
print('i')
switch.default()
def default():
print('foo')
Use it like so.
>>> expression = 'a'
>>> getattr(switch, expression, 'default')()
a
b
c
You can also extract the __dict__ attr if you want an actual dict.
>>> switch.__dict__.get('e', 'default')()
de
You can be similarly explicit with if statements.
def switch(case)
if case == a:
doA()
case = b
if case == b:
doB()
case = c
if case == c:
doC()
return
if case == d:
case = e
if case == e:
doDE()
return
if case == f:
case = g
if case == g:
doFG()
case = h
if case == h:
doH()
return
if case == i:
doI()
foo()
If you're worried about side effects changing the condition or if the conditions are more complex than simple equality and you don't want to repeat them, you can use a helper variable instead of reassigning case.
def switch(case):
fall = False
if case == a:
doA()
fall = True
if fall or case == b:
doB()
fall = True
if fall or case == c:
doC()
return
if case == d:
fall = True
if fall or case == e:
doDE()
return
if case == f:
fall = True
if fall or case == g:
doFG()
fall = True
if fall or case == h:
doH()
return
if case == i:
doI()
foo()
The if statement can do any condition at all. You just have to be a little more explicit.
def switch(case):
if case in 'a':
doA()
if case in 'ab':
doB()
if case in 'abc':
doC()
return
if case in 'de':
doDE()
return
if case in 'fg':
doFG()
if case in 'fgh':
doH()
return
if case in 'i':
doI()
foo()
I have a recursive function that I'm looking to test, however I'm having difficulty limiting the recursive call during testing. For example, below is a simple example of a recursive function that calls a bool_function(n) to check if it should break the recursive loop.
def factorial(n):
if bool_function(n):
return 1
else:
return n * factorial(n-1)
What would be the best way to test or mock bool_function(n) so that it is true for the first iteration and false for any call after?
You could always implement a class to encapsulate the state and give you more flexibility, here's a sketch:
>>> class MockBoolCheck:
... def __init__(self, fail_after=0):
... self.count = 0
... self.fail_after = fail_after
... def __call__(self, n):
... called = self.count
... self.count += 1
... return called <= self.fail_after
...
>>> bool_function = MockBoolCheck()
>>> bool_function(42)
True
>>> bool_function(42)
False
>>> bool_function(42)
False
>>> bool_function(42)
False
>>> bool_function(42)
False
If, beside other suggested solutions, you really want to mock it, and want to do it yourself (without the mocking libraries) by just replacing the mocked function.
# Your code (or module):
def bool_function(n):
print('REAL bool-function {}'.format(n))
return n <= 0
def factorial(n):
print('FACT {}'.format(n))
if bool_function(n):
return 1
else:
return n * factorial(n-1)
# Mocking code (or module):
def mock_function(n):
print('MOCK bool-function {}'.format(n))
global bool_function
bool_function = bool_func_orig # restore on the first use
return False
bool_func_orig = bool_function
bool_function = mock_function # mock it
# Go run it!
factorial(10)
If these are two separate modules, then instead of global bool_function & bool_function=... just use the somemodule.bool_function=....
If you want to use the mocking library, then it depends on which library you use. If that is unittest.mock, then you should play with side_effect=... & wraps=... (see the manual). The same approach: mock it, and un-mock it from inside the side effect on the first use.
I generally try not to leave debug code around unless I expect to use it regularly, but you could just include a default argument for the sake of debugging to force the execution to follow a particular path.
def factorial(n, debug=False):
if bool_function(n) or debug:
return 1
else:
return n * factorial(n-1)
This naturally implies that you're also externally testing bool_function()
Just pass the function as an argument. If function is None you can apply some default behavior if that is desired.
This is a common approach used in queries to iterables (e.g. Django queries or Peewee queries) in most of languages.
A function that returns boolean is usually called a predicate
def factorial(n, predicate=None):
if not predicate:
predicate = lambda x: x > 2
if predicate(n):
return 1
else:
return n * factorial(n-1)
For python > 3.6
import mock
class RecursividadeTest(unittest.TestCase):
def test_recursive(self):
with mock.patch('path.factorial') as mock_fact:
factorial(3)
self.assertTrue(mock_fact.called)
self.assertGreaterEqual(mock_fact.call_count, 2)
def test_recursive_2(self):
with mock.patch('incolumepy.sequences.fibonacci.fibonacci') as mock_fib:
for i in range(1, 5, -1):
expected = i - 1
fibonacci(i)
self.assertTrue(mock_fib.called)
self.assertEqual(mock_fib.call_count, expected)
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
So i'm creating a little experimental python program and I'm using a little tidbit of code (shown below) to determine if a number is whole or has decimal places.
def isWhole(x):
if(x%1 == 0):
return "1"
else:
return "2"
My problem is that no matter where I go I can't find a way to just take the returned value and assign it to a variable...
Sorry if I seem like an absolute spurglord noob for asking this question but I never even knew that functions could "return" until about 2 days ago, so yeah...
like this:
def isWhole(x):
if(x%1 == 0):
return "1"
else:
return "2"
my_var = isWhole(4)
The return value will always be 1.
def isWhole(x):
if x % 1 == 0:
return "1"
else:
return "2"
if __name__ == "__main__":
k = isWhole(4)
print(k)
Answering your question, how to assign a variable, just assign it to the output of the function as below:
var = isWhole(4) #Put any number in instead of 4
As long as you have a return in your function, you can assign a variable to the output:
>>> def foo():
... return "bar"
...
>>> var = foo()
>>> var
"bar"
>>>
However if you do not have a return, then it returns None, so beware :)
>>> def bar():
... print "foo"
...
>>> var = bar()
foo
>>> var
None
>>>
As others have explained, you can just assign the result of calling the function to a variable name to save the value. Perhaps equally important though, is the fact that the code shown in your function will always return "1" since the value of x%1 is always going to be 0 regardless of the value of x (assuming its value is non-zero and a type with a modulo operator).
I would suggest that tou instead implement your function to return a True or False value and do it like the following:
def is_whole(x):
return float(x).is_integer()
(See the is_integer documentation for more information.)
You can assign the result of calling this function to a variable as shown below:
result1 = is_whole(21./7.) # assign function return value to a variable
result2 = is_whole(22./7.) # assign function return value to another variable
print(result1) # --> True
print(result2) # --> False
Consider this code:
def foo(foo_input):
if 0 <= foo_input <= 100:
return f_input
This returns None in the case where foo_input > 100. But could it actually not return anything? Or does a function always have to return something?
See also: return, return None, and no return at all?
Functions always return something (at least None, when no return-statement was reached during execution and the end of the function is reached).
Another case is when they are interrupted by exceptions.
In this case exception handling will "dominate over the stack" and you will return to the appropriate except or get some nasty error :)
Regarding your problem I must say there are two possibilities:
Either you have something to return or you do not have.
If you have something to return then do so, if not then don't.
If you rely on something being returned that has a certain type but you cannot return anything meaningful of this type then None will tell the caller that this was the case (
There is no better way to tell the caller that "nothing" is returned then by None, so check for it and you will be fine)
No. If a return statement is not reached before the end of the function then an implicit None is returned.
If a return statement is not reached, the function returns None.
def set_x():
x = 2
I'm not sure what you really are trying to do. Here are a few things you might like:
def foo(foo_input, foo_default):
if 0 <= foo_input <= 100:
return f_input
else:
return foo_default
def foo(foo_input):
if 0 <= foo_input <= 100:
return f_input
raise ValueError, "foo_input was not in range [0, 100]"
Wait, you said "filter". Are you filtering a series of values and you just want to extract the ones that meet a criteria? That's easy in Python:
def foo_check(x):
return 0 <= x <= 100
filtered_list = [x for x in unfiltered_sequence if foo_check(x)]
And you said "chaining functions". Again that's easy if we are talking about filtering a sequence:
def foo_filter(seq):
for x in seq:
if 0 <= x <= 100:
yield x
def other_filter(seq):
for x in seq:
if meets_criterion(x):
yield x
def do_the_task(seq):
for x in other_filter(foo_filter(seq)):
do_something(x)
EDIT: Here is a nice introduction to iterators and generators in Python. http://www.learningpython.com/2009/02/23/iterators-iterables-and-generators-oh-my/
I sort of like the implicit return None but pylint flags it as bad style, warning:
Either all return statements in a function should return an
expression, or none of them
should.pylint(inconsistent-return-statements)
Hence,
def foo(foo_input):
if 0 <= foo_input <= 100:
return f_input
return None
might be better style, even if they are functionally the same.
More info available here, where the Pylint change-log states:
A new Python checker was added to warn about
inconsistent-return-statements. A function or a method has
inconsistent return statements if it returns both explicit and
implicit values ...
According to PEP8, if any return statement returns an expression, any
return statements where no value is returned should explicitly state
this as return None, and an explicit return statement should be
present at the end of the function (if reachable).
Functions always return something.
All 3 functions below return None:
def test1():
print("test1")
return None
def test2():
print("test2")
return
def test3():
print("test3")