Just one more datapoint given the primary argument for this feature is that it is “easier to understand”:
I personally found
self._lock = lock = RLock() if lock is None
to be much harder to read, parse and reason about than
if lock is None:
lock = RLock()
self._lock = lock
despite already having read the latter first—it reads like a tongue twister to me And I am someone who is used to seeing
lock = RLock() if lock is None else lock
Furthermore, perhaps illustrative of that difficulty, it took careful inspection to tell, but if I’m understanding it correctly these two blocks are not equivalent—the first only assigns lock
to self._lock
if lock is None
, but not if a non-None
value is passed. Unless I’m misunderstanding the exact effect of this syntax—which would be another issue with it, indeed.
Similarly, to me this:
self._acquire_restore = lock._acquire_restore if hasattr(lock, '_acquire_restore')
is harder to read, parse and reason about than the existing
if hasattr(lock, '_acquire_restore'):
self._acquire_restore = lock._acquire_restore
or the existing alternative with getattr:
self._acquire_restore = getattr(lock, '_acquire_restore', self._acquire_restore)
So, FWIW, I’d find this a net decrease in overall readability of the language even in the example cases, not to mind the combinatoric complexity with other expressions/statements as others have raised above.