diff --git a/pep-0572.rst b/pep-0572.rst index bd8dcb2bb..3581a8ead 100644 --- a/pep-0572.rst +++ b/pep-0572.rst @@ -359,6 +359,127 @@ found in assignment statements: Examples ======== +Examples from the Python standard library +----------------------------------------- + +site.py +^^^^^^^ + ++-----------------------------------------------------+------------------------------------------------------------+ +| 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. + +_pydecimal.py +^^^^^^^^^^^^^ ++----------------------------------------------+-----------------------------------------------------------------------+ +| 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.py +^^^^^^^ + +(See Appendix A for the origin of this example.) + ++---------------------------------------------------------------+---------------------------------------------------------------+ +| 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.py +^^^^^^^^^^^ + ++-----------------------------------------------------+-----------------------------------------------------+ +| 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.py +^^^^^^^^^^^^ + ++------------------------------------+-----------------------------------------+ +| 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 ------------------------------- @@ -760,7 +881,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. @@ -804,7 +925,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, @@ -835,7 +956,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: @@ -854,9 +975,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