Arunkumar Navasiva
Arunkumar Navasiva

Reputation: 65

Multiple context managers in a "with" statement in python

I'm curious why the following code:

l1= threading.Lock()
l2= threading.Lock()
l3=threading.Lock()
with l1 and l2 and l3:
  print l1.locked()
  print l2.locked()
  print l3.locked()

prints this:

False
False
True

I realize that the right syntax is:

with l1, l2, l3:

but I'm trying to find an explanation for why only l3 was locked.

Upvotes: 0

Views: 1078

Answers (1)

kaya3
kaya3

Reputation: 51034

To understand this, consider how and works in Python.

The result of the expression x and y is equivalent to y if x else x, except that it only evaluates x once. That is, when bool(x) is True, the and operator results in y, otherwise it results in x (and doesn't evaluate y).

Unless an object defines its own __bool__ dunder method, bool(obj) will generally be True. This is the case for lock objects. So bool(l1) is True, and the expression l1 and l2 and l3 evaluates as l2 and l3. Then since bool(l2) is True, this expression evaluates as l3.

So the with statement ends up managing the lock l3, and therefore that's the one which is locked in the body of the with statement. As you note, if you want to manage multiple locks at once, you should pass them separated by commas.

Upvotes: 4

Related Questions