PEP 572: Add examples from the stdlib by vstinner · Pull Request #695 · python/peps
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
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