[Python-Dev] Assignment expression and coding style: the while True case (original) (raw)
Victor Stinner vstinner at redhat.com
Wed Jul 4 18:51:37 EDT 2018
- Previous message (by thread): [Python-Dev] Tone it down on Twitter?
- Next message (by thread): [Python-Dev] Assignment expression and coding style: the while True case
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Hi,
Let's say that the PEP 572 (assignment expression) is going to be approved. Let's move on and see how it can be used in the Python stdlib.
I propose to start the discussion about "coding style" (where are assignment expressions appropriate or not?) with the "while True" case.
I wrote a WIP pull request to use assignment expressions in "while True": https://github.com/python/cpython/pull/8095/files
In short, replace:
while True:
x = expr
if not x:
break
...
with:
while (x := expr):
...
My question is now: for which "while True" patterns are the assignment expression appropriate? There identified different patterns.
== Pattern 1, straighforward ==
while True: line = input.readline() if not line: break ...
IMHO here assingment expression is appropriate here. The code remains straighfoward to read.
while (line := input.readline()): ...
== Pattern 2, condition ==
Condition more complex than just "not line":
while True: q = c//n if n <= q: break ...
replaced with:
while (q := c//n) < n: ...
IMHO it's still acceptable to use assignement expression... Maybe only for basic conditions? (see above)
== Pattern 3, double condition ==
while True: s = self.__read(1) if not s or s == NUL: break ....
replaced with:
while (s := self.__read(1)) and s != NUL: ...
Honestly, here, I don't know if it's appropriate...
At the first look, "s != NUL" is surprising, since "s" is not defined before the while, it's only defined in the first test (defining a variable inside a test is currently uncommon in Python).
== Pattern 4, while (...): pass ==
Sometimes, the loop body is replaced by "pass".
while True: tarinfo = self.next() if tarinfo is None: break
replaced with:
while (tarinfo := self.next()) is not None: pass
It reminds me the surprising "while (func());" or "while (func()) {}" in C (sorry for theorical C example, I'm talking about C loops with an empty body).
Maybe it's acceptable here, I'm not sure.
Note: such loop is rare (see my PR).
== Pattern 5, two variables ==
while True: m = match() if not m: break j = m.end() if i == j: break ...
replaced with:
while (m := match()) and (j := m.end()) == i: ...
Maybe we reached here the maximum acceptable complexity of a single Python line? :-)
== Other cases ==
I chose to not use assignment expressions for the following while loops.
(A)
while True: name, token = _getname(g) if not name: break ...
"x, y := ..." is invalid. It can be tricked using "while (x_y := ...)[0]: x, y = x_y; ...". IMHO it's not worth it.
(B)
while True: coeff = _dlog10(c, e, places) # assert len(str(abs(coeff)))-p >= 1 if coeff % (510*(len(str(abs(coeff)))-p-1)): break places += 3
NOT replaced with:
while not (coeff := _dlog10(c, e, places)) % (510*(len(str(abs(coeff)))-p-1)): places += 3
^-- Tim Peters, I'm looking at you :-)
coeff is defined and then "immediately" used in "y" expression of x%y... Yeah, it's valid code, but it looks too magic to me...
(C)
while True: chunk = self.raw.read() if chunk in empty_values: nodata_val = chunk break ...
"nodata_val = chunk" cannot be put into the "chunk := self.raw.read()" assignment expression combined with a test. At least, I don't see how.
(D)
while 1: u1 = random() if not 1e-7 < u1 < .9999999: continue ...
Again, I don't see how to use assignment expression here.
Victor
- Previous message (by thread): [Python-Dev] Tone it down on Twitter?
- Next message (by thread): [Python-Dev] Assignment expression and coding style: the while True case
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]