[Soni L. <fakedme...@gmail.com>]
> That ain't shadow. That is dynamic scoping.

I don't believe either term is technically accurate, but don't really care.


> Shadowing is something different:
>
> def f():
>     a = 42
>     def g():
>         print(a)
>     local a:
>         a = 43
>         g()
>     g()
>
> should print "42" both times, *if it's lexically scoped*.

Why?  The `local` statement, despite its name, and casual talk about
it, isn't _intended_ to create a new scope in any technically accurate
sense.  I think what it is intended to do has been adequately
explained several times already.  The `a` in `a = 42` is intended to
be exactly the same as the `a` in `a = 43`, changing nothing at all
about Python's lexical scoping rules.  It is _the_ `a` local to `f`.
If lexical scoping hasn't changed one whit (and it hasn't), the code
_must_ print 43 first.  Same as if `local a:` were replaced by `if
True:`.  `local` has no effect on a's value until the new "scope"
_ends_, and never any effect at all on a's visibility (a's "scope").
"local" or not, after `a = 43` there is no scope anywhere, neither
lexical nor dynamic, in which `a` is still bound to 42.  _The_ value
of `a` is 43 then, `local` or not.

The _only_ twist is that `local` wants to save/restore `a`'s binding
before/after the suite of code it controls.  That's not really about
"scope" at all with its technical meaning.  I don't much care if
people casually _think_ about it as being "about.scope", though.

Yes, the effect is similar to what you might see in a language with
dynamic scoping _if_ it pushed a _copy_ of a's current <name, object>
binding on an evaluation stack at the start, and popped that (possibly
mutated) copy later, but actual dynamic binding doesn't push copies,
and Python isn't using any sort of dynamic evaluation stack
regardless.  That both restore previous bindings at times is a shallow
coincidence.  Neither is it really shadowing, which is lexical hiding
of names.  Neither is an accurate model for what it actually does,
but, yes, it bears more _resemblance_ to dynamic scoping if you ignore
that it's not dynamic scoping ;-)


> If it's lexically scoped, this is just adding another scope: blocks.
> (instead of the smallest possible scope being function scope)

I expect that thinking about "scope" at all just confuses people here,
unless they don't think too much about it ;-)  Nothing about Python's
scoping rules changes one whit.  Exactly the same in the above could
be achieved by replacing the `local a:` construct above by, e.g,,

    __save_a_with_a_unique_name = a
    a = 43
    g()
    a =  __save_a_with_a_unique_name

Indeed, that's one way the compiler could _implement_ it.  Nothing
about a's scope is altered; it's merely a block-structured
save-value/restore-value gimmick.
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to