The existing implementation has optimizations here. If that's important, we could achieve the same result with a little dataflow analysis to optimize away the dead store. We could even special-case optimizing away dead stores only to '_' and only in match/case statements and all would be forgiven.
This might work, although it's quite different to what python does in general (are you supposed to see the value of `_` in a debugger? or in `locals()`? )
All excellent points. The debugger question is easier to answer. Debuggers for compiled code have dealt with this for years; I'm unsure of the exact wording but gdb prints something like "<value optimized out>".
As for locals(), my first thought was "suppress the optimization
in the presence of a locals() call". I dimly recall a precedent
where the presence of locals() in a function body
affected code generation, though sadly it escapes me at the
moment**. Anyway, that seems like a nasty hack, and it only
handles one method of extracting a locals dict--there's several
more, including sys._getframe and inspect.getframeinfo. And then
the user could rebind those and we wouldn't notice. This seems
like a non-starter.
Having thought about it some, I propose it'd be acceptable to do
dead store optimization if-and-only-if optimizations are
explicitly enabled, e.g. with "-O". Allowing explicitly-enabled
optimizations to observably affect runtime behavior does have some
precedent, e.g. "-OO" which breaks doctest, docopt, etc. It'd be
a shame if the existence of locals() et al meant Python could
never ever perform dead store optimization.
Your other (elided) point is correct too, about sequence matching
for a sequence we don't care about not being as cheap and simple
as a store and an extra reference.
Cheers,
/arry
** Or maybe I'm confused and thinking of something else
entirely. Maybe it was "import * inside a function body disables
fast locals in Python 2"? But that doesn't seem to be true
either.