On 25 Apr, 2018, at 5:20 PM, Chris Angelico <rosuav@gmail.com> wrote:
On Thu, Apr 26, 2018 at 10:11 AM, Yury Selivanov <yselivanov.ml@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. -- Ł