PEP 572: Add examples from the stdlib by vstinner · Pull Request #695 · python/peps (original) (raw)

Expand Up

@@ -359,6 +359,125 @@ found in assignment statements:

Examples

========

Examples from the Python standard library

-----------------------------------------

site

^^^^

+-----------------------------------------------------+------------------------------------------------------------+

| Current code | Replaced with |

+-----------------------------------------------------+------------------------------------------------------------+

| | |

| :: | :: |

| | |

| env_base = os.environ.get("PYTHONUSERBASE", None) | if (env_base := os.environ.get("PYTHONUSERBASE", None)): |

| if env_base: | return env_base |

| return env_base | |

| | |

+-----------------------------------------------------+------------------------------------------------------------+

*env_base* is only used on these lines, putting its assignment on the if

moves it as the "header" of the block.

decimal

^^^^^^^

+----------------------------------------------+-----------------------------------------------------------------------+

| Current code | Replaced with |

+----------------------------------------------+-----------------------------------------------------------------------+

| | |

| :: | :: |

| | |

| if self._is_special: | if self._is_special and (ans := self._check_nans(context=context)): |

| ans = self._check_nans(context=context) | return ans |

| if ans: | |

| return ans | |

| | |

+----------------------------------------------+-----------------------------------------------------------------------+

Avoid nested if and remove one indentation level.

copy

^^^^

+---------------------------------------------------------------+---------------------------------------------------------------+

| Current code | Replaced with |

+---------------------------------------------------------------+---------------------------------------------------------------+

| | |

| :: | :: |

| | |

| reductor = dispatch_table.get(cls) | if (reductor := dispatch_table.get(cls)): |

| if reductor: | rv = reductor(x) |

| rv = reductor(x) | elif (reductor := getattr(x, "__reduce_ex__", None)): |

| else: | rv = reductor(4) |

| reductor = getattr(x, "__reduce_ex__", None) | elif (reductor := getattr(x, "__reduce__", None)): |

| if reductor: | rv = reductor() |

| rv = reductor(4) | else: |

| else: | raise Error("un(deep)copyable object of type %s" % cls) |

| reductor = getattr(x, "__reduce__", None) | |

| if reductor: | |

| rv = reductor() | |

| else: | |

| raise Error( | |

| "un(deep)copyable object of type %s" % cls) | |

+---------------------------------------------------------------+---------------------------------------------------------------+

Code looks more regular and avoid multiple nested if.

datetime

^^^^^^^^

+-----------------------------------------------------+-----------------------------------------------------+

| Current code | Replaced with |

+-----------------------------------------------------+-----------------------------------------------------+

| | |

| :: | :: |

| | |

| s = _format_time(self._hour, self._minute, | s = _format_time(self._hour, self._minute, |

| self._second, self._microsecond, | self._second, self._microsecond, |

| timespec) | timespec) |

| tz = self._tzstr() | if (tz := self._tzstr()): |

| if tz: | s += tz |

| s += tz | return s |

| return s | |

| | |

+-----------------------------------------------------+-----------------------------------------------------+

*tz* is only used for ``s += tz``, moving its assignment inside the if

helps to show its scope.

sysconfig

^^^^^^^^^

+------------------------------------+-----------------------------------------+

| Current code | Replaced with |

+------------------------------------+-----------------------------------------+

| | |

| :: | :: |

| | |

| while True: | while (line := fp.readline()): |

| line = fp.readline() | if (m := define_rx.match(line)): |

| if not line: | n, v = m.group(1, 2) |

| break | try: |

| m = define_rx.match(line) | v = int(v) |

| if m: | except ValueError: |

| n, v = m.group(1, 2) | pass |

| try: | vars[n] = v |

| v = int(v) | elif (m := undef_rx.match(line)): |

| except ValueError: | vars[m.group(1)] = 0 |

| pass | |

| vars[n] = v | |

| else: | |

| m = undef_rx.match(line) | |

| if m: | |

| vars[m.group(1)] = 0 | |

| | |

+------------------------------------+-----------------------------------------+

Calling ``fp.readline()`` in the ``while`` condition and calling

``.match()`` on the if lines make the code more compact without making

it harder to understand.

Simplifying list comprehensions

-------------------------------

Expand Down Expand Up

@@ -760,7 +879,7 @@ ruled::

is a vast improvment over the briefer::

yield (mylast := mylast[1])[0]

The original two statements are doing entirely different conceptual

things, and slamming them together is conceptually insane.

Expand Down Expand Up

@@ -804,7 +923,7 @@ pattern-matching reading, as::

if result := solution(xs, n):

# use result

It's also nice to trade away a small amount of horizontal whitespace

to get another _line_ of surrounding code on screen. I didn't give

much weight to this at first, but it was so very frequent it added up,

Expand Down Expand Up

@@ -835,7 +954,7 @@ is conceptually flat, "the first test that succeeds wins"::

if reductor := dispatch_table.get(cls):

rv = reductor(x)

elif reductor := getattr(x, "__reduce_ex__", None):

rv = reductor(4)

rv = reductor(4)

elif reductor := getattr(x, "__reduce__", None):

rv = reductor()

else:

Expand All

@@ -854,9 +973,9 @@ annoying "artificial" indentation level::

g = gcd(diff, n)

if g > 1:

return g

became::

if (diff := x - x_base) and (g := gcd(diff, n)) > 1:

return g

Expand Down