1

I encountered a bug in some code. The (incorrect) line was similar to:

[x for x in range(3, 6) and range(0, 10)] 
print x

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

(the correct way of writing this statement is not part of the question)

Wondering what someList and someOtherList does, I experimented. It seems to only ever set the result to the last parameter passed:

x = range(0,3)   # [0, 1, 2]
y = range(3, 10) # [3, 4, 5, 6, 7, 8, 9]
z = range(4, 8)  # [4, 5, 6, 7]

print x and y       # [3, 4, 5, 6, 7, 8, 9]
print y and x       # [0, 1, 2]
print z and y and x # [0, 1, 2]

I would assume that this is an unintentional consequence of being able to write something that is useful, but I'm not really seeing how the semantics of the "and" operator are being applied here.

From experience, python won't apply operators to things that don't support those operators (i.e. it spits out a TypeError), so I'd expect an error for and-ing something that should never be and-ed. The fact I don't get an error is telling me that I'm missing... something.

What am I missing? Why is list and list an allowed operation? And is there anything "useful" that can be done with this behaviour?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
KidneyChris
  • 857
  • 5
  • 12
  • 1
    that question is about booleans but the answer applies regardless of the types – Tim Apr 07 '17 at 09:55
  • Thanks @TimCastelijns – KidneyChris Apr 07 '17 at 10:01
  • I do think the linked question could mention that the problem isn't just boolean lists (it's any list), but I'm not really adding much here. Happy to close as duplicate. – KidneyChris Apr 07 '17 at 10:05
  • the answer mentions it *Their contents don't play a role here.* – Tim Apr 07 '17 at 10:11
  • Hi @TimCastelijns; I saw that the *answer* mentions that (hence happy to close as dupe), but that the *question* might not get people to the right place (example: I didn't see that question when I was searching about my non-boolean lists :-) ). – KidneyChris Apr 07 '17 at 12:04
  • OK well I googled "python and operator list" and it was the first hit – Tim Apr 07 '17 at 13:22

1 Answers1

2

The and operator checks the truthiness of the first operand. If the truthiness is False, then the first argument is returned, otherwise the second.

So if both range(..)s contain elements, the last operand is returned. So your expression:

[x for x in range(3, 6) and range(0, 10)]

is equivalent to:

[x for x in range(0, 10)]

You can however use an if to filter:

[x for x in range(3, 6) if x in range(0, 10)]

In range(..) however constructs a list, making it not terribly efficient. Since we know that x is an int, we can do the bounds check like:

[x for x in range(3, 6) if 0 <= x < 10]

Of course in this case the check is useless since every element in range(3,6) is in the range of range(0,10).

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555