Mailing List Archive

Scope confusion in Python REPL
I ran into what seems odd scoping to me when playing with some matching
examples for 3.10.

I kinda thought that if I do from foo import * and from bar import * in
the Python REPL, I'd get everything from foo and bar in the main
scope. Or whatever the scope is at the prompt.

And yet, if I define function foo in module foo and function bar in
module bar and import as above, I can't call function bar from function
foo. But if I define functions foo and bar at the prompt, then I can. So
what's the difference in scoping here?
--
https://mail.python.org/mailman/listinfo/python-list
Re: Scope confusion in Python REPL [ In reply to ]
On Thu, Jan 13, 2022 at 9:43 PM Anssi Saari <as@sci.fi> wrote:
>
>
> I ran into what seems odd scoping to me when playing with some matching
> examples for 3.10.
>
> I kinda thought that if I do from foo import * and from bar import * in
> the Python REPL, I'd get everything from foo and bar in the main
> scope. Or whatever the scope is at the prompt.

That is correct.

> And yet, if I define function foo in module foo and function bar in
> module bar and import as above, I can't call function bar from function
> foo. But if I define functions foo and bar at the prompt, then I can. So
> what's the difference in scoping here?

That's because, *inside function bar*, you don't have foo in scope.
Both functions are available at the REPL's module scope, but they both
exist in their own contexts.

When you define a function, it remembers its context. Inside that
function, you can refer to anything else in the function, or in any
surrounding function, or in the module. That's how closures work:

def make_adder(a):
def adder(b):
return a + b
return adder

Whenever you call make_adder, it will give you back a brand new
function, which will remember the value of 'a'.

The same is true of module-level names. If I have a function like this:

a = 42
def adder(b):
return a + b

and I import that function into some other module, it'll use 'a' from
its own module globals, not the module you're calling it from.

When you import something, all you're doing is getting a local
reference to it; "from foo import make_adder" is basically like saying
"import foo; make_adder = foo.make_adder". The function itself is
still the same, and it still remembers its original context.

Defining two functions at the prompt is like putting them in the same
file; they're able to refer to each other directly. What you may want
to do is have one module import the other one, which would then allow
them to refer to each other.

Hope that helps!

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: Scope confusion in Python REPL [ In reply to ]
Chris Angelico <rosuav@gmail.com> writes:

> When you import something, all you're doing is getting a local
> reference to it; "from foo import make_adder" is basically like saying
> "import foo; make_adder = foo.make_adder". The function itself is
> still the same, and it still remembers its original context.

Thanks, this clears it up.

The pattern matching examples that I was looking at when I got confused
are at
https://mathspp.com/blog/pydonts/pattern-matching-tutorial-for-pythonic-code
in case anyone is interested. Fairly neat stuff in my opinion.
--
https://mail.python.org/mailman/listinfo/python-list