Hacker News new | past | comments | ask | show | jobs | submit login

Python also has "shorthand ternary" which uses and/or:

    a = bar and foo # "or None" is implied
    b = bar and foo or baz
It does almost the same but not quite. In the latter example, if foo is falsey, it evaluates to "b = baz":

    b = bar ? (foo ? foo : baz) : baz



Woah! I was all ready to disagree with you, saying 'only for Boolean arguments'. In years of writing python I really thought `__and__`/`__or__` returned Boolean. (Of course they can, but for builtins I mean.)

https://docs.python.org/3/reference/datamodel.html#emulating...

It's not made clear here that I can see. Grr, needs type annotations!


That's the wrong part of the doc. You refer to the binary operators || and &&, etc.

This is the correct part: https://docs.python.org/3/reference/expressions.html?highlig...

Edit: you can't override "and" and "or" with dunder methods.


Ahh of course, thanks!


See the language around short-circuiting here

https://docs.python.org/3/library/stdtypes.html#boolean-oper...

The expression is returned based on its truthiness


Is this official, encouraged syntax? It looks like it's just exploiting short-circuit evaluation. `bar && foo || baz` works in Javascript as well for example.


No.

In fact, nearly 20 years ago PEP 308 ("Conditional Expressions") was made so people wouldn't need to resort to this sort of syntax - https://www.python.org/dev/peps/pep-0308/ .

Quoting from the Python FAQ from 2.6 at https://web.archive.org/web/20151030070641if_/https://docs.p... :

> In many cases you can mimic a ? b : c with a and b or c, but there’s a flaw: if b is zero (or empty, or None – anything that tests false) then c will be selected instead. In many cases you can prove by looking at the code that this can’t happen (e.g. because b is a constant or has a type that can never be false), but in general this can be a problem.

> Tim Peters (who wishes it was Steve Majewski) suggested the following solution: (a and [b] or [c])[0].


I have seen it a lot of code over the years, sometimes referred to as "shorthand ternary" or the "and-or-trick". In Python and/or do not return a boolean, but one of its input arguments. So I am going to say it is official syntax, but I don't know to what extent it's encouraged


Not only in python, but in most scripting languages. It’s hard to find one that doesn’t. But it’s neither official, nor ternary syntax anywhere.

  true and false or true
  true ?   false :  true
These are not equivalent. If the second argument is evaluated as false, the “ternary” breaks.

Lua suggests to use this as ternary, but it has only two false values (nil, false), which reduces the number of problematic cases a little.


It saves a character in code golf, but as others have pointed out, it's unsafe.

    a if b else c #+1 byte
    a and b or c  #buggy
    (c,b)[not a]  #ok in general
    a and 1or c   #-1 byte if b is a constant
    (b,c)[a]      #-4 byte if a is boolean


or None is not implied

    >>> repr(False and False)
    'False'
    >>> repr(False and False or None)
    'None'
False is not None

    >>> False == None
    False


As it's error prone, and only saves 1 character, it's not a great shorthand.


EDIT2: What I was replying to is no longer there.

It does short circuit, your logic is just purposely fragile. If you reverse the variables it will print Empty, because the and statement evaluates left to right and stops if one of the arguments is falsey.

  print(len(foo) > 0 and foo[0]  or "Empty")
And since len can't give negative numbers the more Pythonic way to do it would be like this. Even though I generally prefer normal if blocks.

  print(len(foo) and foo[0]  or "Empty")

edit: I do agree that you should probably avoid doing this at all, because it is easy to introduce subtle bugs.


My logic wasn't purposely fragile, I missed that the test goes on the left hand size of the 'and', which makes my case that it's error prone ;)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: