In Dive in to Python I read about the peculiar nature of and
and or
operators
and how shortcircuit evaluation of boolean operators may be used to express conditionals more succinctly via the and-or trick that works very much like the ternary operator in C.
C:
result = condition ? a : b
Python:
result = condition and a or b
This seems to come in handy since lambda functions are restricted to one-liners in Python, but it uses logical syntax to express control flow.
Since Python 2.5 the inline-if
seems to have come to the rescue as a more readable syntax for the and-or trick:
result = a if condition else b
So I guess that this is the pythonic replacement for the less readable and-or-construct. Even if I want to nest multiple conditions, it still looks quite comprehensive:
result = a if condition1 else b if condition2 else c
But in a world of uncertainity I frequently find myself writing some code like this to access a.b.c :
result = a and hasattr(a, 'b') and hasattr(a.b, 'c') and a.b.c or None
So with the help of inline-if I could probably get rid of some ands and ors, resulting in a quite readable piece of code:
result = a.b.c if hasattr(a, 'b') and hasattr(a.b, 'c') else None
I also discovered a somewhat arcane approach for conditonals in this recipe
result = (a, b)[condition]
but this doesn't short-circuit and will result in all kinds of errors if the result of the condition does not return a boolean, 0 or 1.
Now I wonder if it is considered preferable / more pythonic to use the inline-if
as much as possible if downwards compatibility is not a concern, or is all just a matter of taste and how much one feels at home in the world of short-circuit evaluation?
I just realized that inline-if is more than syntactic sugar for the and-or-trick, since it will not fail when a
is false in a boolean context. So It's probably more fail-proof.
The pythonic thing to do is recognise when you've stretched your code past what is sensible to cram into a single function and just use an ordinary function. Remember, there is nothing you can do with a lambda
that couldn't also be done with a named function.
The breaking point will be different for everyone of course, but if you find yourself writing:
return a.b.c if hasattr(a, 'b') and hasattr(a.b, 'c') else None
too much, consider just doing this instead:
try:
return a.b.c
except AttributeError:
return None
Since there is is a special language construct with the inline if
-else
that does what you want and which was introduced to replace ugly workarounds like those you mention, it is a good idea to use it. Especially since hacks like the and
-or
trick usually have unexpected corner cases/bugs.
The and
-or
trick for example fails in this case:
a = 0
b = 1
c = True and a or b
c
will be 1
, which is not what you expect if you are looking for if
-else
semantics.
So why use buggy workarounds when there is a language construct that does exactly what you want?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With