4

I have to maintain a python package which was no longer updated since 2008. I guess the Python version the developer used back then was 2.3 or 2.4, I guess. Mostly the source code is the same, but I found something like:

fsa = (fsa and union(fsa, fsa2)) or fsa2

where fsa, fsa2, union(fsa, fsa2) are all objects. I have no idea how they work to return the new object. Could somebody please give me some hint? Also, Are these operators still allowed in Python 2.7? If no, how do I change it to make it work properly in Python 2.7?

Thanks,

Loi.Luu
  • 373
  • 3
  • 15

3 Answers3

6

Have a look at this page in the documentation: http://docs.python.org/3.3/faq/programming.html#is-there-an-equivalent-of-c-s-ternary-operator

In older versions of Python the "and-or" idiom was used to emulate a ternary operator. In modern Python you'd write the above expression as

fsa = union(fsa, fsa2) if fsa else fsa2

The trick is the short-cutting behaviour of and and or in Python:

  • a and b evaluates to b if a as a boolean evaluates to True, otherwise it evaluates to a
  • a or b evaluates to b if a as a boolean evaluates to False, otherwise it evaluates to a

Put this together and you have a nice ternary operator emulation :)

EDIT: However, as Alfe rightfully commented, this is not exactly equivalent. If union(fsa, fsa2) is False as a boolean (i.e. if the union function returned None) the existing code would return fsa2 while the "modern" code would return None or whatever false value union returned. I'd stick with the existing code since it continues to work in newer python versions and document it. Have a look at the implementation of union to decide whether you want to transition to the modern, IMHO cleaner, syntax.

filmor
  • 30,840
  • 6
  • 50
  • 48
  • 2
    This is probably what is intended by that `and` ... `or` idiom, but it is not exactly the same as the ternary. If `union(fsa, fsa2)` returns a _falsy_ value, the result will be `fsa2`, regardless of the value of `fsa`. – Alfe Feb 26 '14 at 08:43
2

Your one line is equivalent of this two ifs:

if fsa:
    fsa = union(fsa, fsa2):

if not fsa:
    fsa = fsa2

This way (fsa = (fsa and union(fsa, fsa2)) or fsa2) of using boolean operators is called short-circuiting.

There is some info in python docs and relevant questions, for example: Does Python support short-circuiting?

Community
  • 1
  • 1
ndpu
  • 22,225
  • 6
  • 54
  • 69
2

and and or each return one of their operands. and returns the first which is falsy (or the last if none is), or returns the first which is truthy (or the last if none is).

Falsy and truthy refer to the boolean value of the object; empty strings, empty arrays etc. all are falsy.

Alfe
  • 56,346
  • 20
  • 107
  • 159