On 05.07.2018 1:51, Victor Stinner wrote:
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.
Would be more readable with a more descriptive variable name:

while (chunk := self.next()) is not None:
    pass
tarinfo = chunk


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? :-)
Would be more readable with additional parentheses:

while (m := match()) and ((j := m.end()) == i):



== 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 % (5*10**(len(str(abs(coeff)))-p-1)):
         break
     places += 3

NOT replaced with:

while not (coeff := _dlog10(c, e, places)) % (5*10**(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.
Here, unlike the previous example, the assignment is a subexpression of the conditions, so it _can_ be inlined:

while  (u1:=random()) < 1e-7 or u1 > .9999999:

Victor
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/vano%40mail.mipt.ru

--
Regards,
Ivan

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to