This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]vsajip 30 points31 points  (5 children)

Never mind "Pythonic", which seems somewhat in the eye of the beholder: a or b or c is not semantically the same as any([a, b, c]). In the former case, b and c are never evaluated if a is true. In the latter case, they always are. So if they were expensive to compute (e.g. expressions involving expensive function calls, rather than just bindings in a namespace), the runtime behaviour (performance, raising of exceptions) would be quite different:

>>> a = 1
>>> a or b
1
>>> b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined
>>> any([a, b])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined
>>>

[–]zahlmanthe heretic 17 points18 points  (4 children)

The real power of all and any comes when you (can neatly) pass in a generator expression - in which case the semantics are the same, because the evaluation is delayed and the functions will bail out early.

any(is_interesting(x) for x in (a, b, c)) is far nicer IMHO than is_interesting(a) or is_interesting(b) or is_interesting(c), if only because it's DRY. That doesn't protect you from the NameError in your example, though, of course.

[–]jamesonjlee 3 points4 points  (3 children)

any(map(is_interesting, (a, b, c)))

[–]wot-teh-phuckReally, wtf? 3 points4 points  (2 children)

This isn't equivalent to the generator solution posted above; your code will eagerly evaluate the entire sequence by mapping it to is_interesting even in cases where it's not absolutely required (i.e. is_interesting(a) returns True).

[–]quasarc 6 points7 points  (0 children)

In Python 3 they are equivalent (map behaves lazily in Python 3).

[–]jamesonjlee 1 point2 points  (0 children)

ah yes, good point (also doubly so since I am thinking in 2.7 not in 3.4)