[Python-Dev] (name := expression) doesn't fit the narrative of PEP 20
Łukasz Langa
lukasz at langa.pl
Wed Apr 25 21:52:34 EDT 2018
> On 25 Apr, 2018, at 5:20 PM, Chris Angelico <rosuav at gmail.com> wrote:
>
> On Thu, Apr 26, 2018 at 10:11 AM, Yury Selivanov
> <yselivanov.ml at gmail.com> wrote:
>> Just yesterday this snippet was used on python-dev to show how great the
>> new syntax is:
>>
>> my_func(arg, buffer=(buf := [None]*get_size()), size=len(buf))
>>
>> To my eye this is an anti-pattern. One line of code was saved, but the
>> other line becomes less readable. The fact that 'buf' can be used after
>> that line means that it will be harder for a reader to trace the origin of
>> the variable, as a top-level "buf = " statement would be more visible.
>
> Making 'buf' more visible is ONLY a virtue if it's going to be used
> elsewhere. Otherwise, the name 'buf' is an implementation detail of
> the fact that this function wants both a buffer and a size.
You're claiming that `:=` is nicer in this situation because it's less
prominent than regular assignment and thus doesn't suggest that the name
stays visible later.
But as others said, `:=` *does* make the name visible later until the
enclosing scope ends. In fact, a large part of its appeal is that you
can use the result later (as in the `re.search()` example). Will it be
visible enough to the reaser in those cases then?
There seems to be a conflict there.
The question of assignment visibility also makes me think about
unintentional name shadowing::
buf = some_value
... # 20 lines
my_func(arg, buffer=(buf := [None]*get_size()), size=len(buf))
... # 20 lines
buf # <-- What value does this have?
Even if we're not using the call pattern, there can be plenty of logic
tests which aren't very obvious::
buf = some_value
... # 20 lines
if node.parent is not None and (buf := node.parent.buffer):
... # 10 lines
... # 20 lines
buf # <-- What value does this have?
This is even more interesting because now `buf` isn't rebound
*always*.
So if I'm confused about an unexpected change in value of `buf`, I'll
skim the code, fail to find the assignment, and then grep for `buf =`
and also fail to find the assignment. Yes, I could have searched for
just `buf` instead but that will give me too many false positives,
especially if I'm using a primitive text editor search or don't know
about \b in regular expressions.
Debugging this can be confusing. I know it can since a similar
annoyance can be observed with the magic pseudo-scope of `except`::
err = some_value
try:
...
except Error as err:
...
err # <-- now sometimes it's not defined
Just like Barry, I debugged a few cases of this in the past and within
larger functions this can be hard to find.
-- Ł
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180425/9d2fbb9d/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Message signed with OpenPGP
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180425/9d2fbb9d/attachment.sig>
More information about the Python-Dev
mailing list