Where is my namespace?

V

vsoler

I take the example from Mark Lutz's excellent book "Learning Python".

*** In nested1.py I have:
X=99
def printer(): print X

*** In nested2.py I have:
from nested1 import X, printer
X=88
printer()

What is amazing is that running nested2.py prints 99 and not 88.

My questions are:

1. Using statement "from" instead of "import" should not create a
namespace, at least that's what I think. However, the printer()
function is able to find 99 which is residing in... a namespace?

2. I have tried to access the 88 by qualification from nested2.py.
However, I cannot. If using "print nested1.X" in nested2.py I get an
error

3. Mark says: The from statement is really an assignment to names in
the importer's scope--a name-copy operation, not a name aliasing. I
don't fully understand what he means. Could anybody explain?

Thank you very much for your time.

Vicente Soler
 
S

Simon Brunning

2009/12/7 vsoler said:
I take the example from Mark Lutz's excellent book "Learning Python".

*** In nested1.py  I have:
X=99
def printer(): print X

*** In nested2.py  I have:
from nested1 import X, printer
X=88
printer()

What is amazing is that running nested2.py prints 99 and not 88.

My questions are:

1. Using statement "from" instead of "import" should not create a
namespace, at least that's what I think. However, the printer()
function is able to find 99 which is residing in...  a namespace?

Sorry - you think wrong. All modules have their own namespace.

"from blah import" injects the objects from the imported module
directly into the importing modules namespace, but they are still two
distinct namespaces.
2. I have tried to access the 88 by qualification from nested2.py.
However, I cannot. If using "print nested1.X" in nested2.py I get an
error

If you do "from blah import" the imported module itself isn't bound to
any name in the importing module - you can't get at it at all.
3. Mark says: The from statement is really an assignment to names in
the importer's scope--a name-copy operation, not a name aliasing.   I
don't fully understand what he means. Could anybody explain?

Does the above help?
 
B

Bruno Desthuilliers

vsoler a écrit :
I take the example from Mark Lutz's excellent book "Learning Python".

*** In nested1.py I have:
X=99
def printer(): print X

*** In nested2.py I have:
from nested1 import X, printer
X=88
printer()

What is amazing is that running nested2.py prints 99 and not 88.

It's "amazing" only if you believe Python's "global" scope is really
global. Thruth is that in Python, "global" means "module-level" - so
when you call printer, it resolves X in it's own "global" namespace -
that is, nested1's global namespace.
My questions are:

1. Using statement "from" instead of "import" should not create a
namespace,

It doesn't.
at least that's what I think. However, the printer()
function is able to find 99 which is residing in... a namespace?

Yes, cf above. This namespace is created when the nested1.py module is
first loaded (whether via any form of import or via direct execution of
nested1 as a script).
2. I have tried to access the 88 by qualification from nested2.py.
However, I cannot. If using "print nested1.X" in nested2.py I get an
error

You have to import the nested1 module itself, ie:

# nested3.py
import nested1

print nested1.X
printer()
nested1.X = 42
printer
3. Mark says: The from statement is really an assignment to names in
the importer's scope--a name-copy operation, not a name aliasing. I
don't fully understand what he means. Could anybody explain?

Think of Python's namespaces as dicts, where names are keys and
reference to objects are values.

If you do:

import nested1

then your current namespace will look like :

{"nested1" : <module 'nested1' from /path/to/nested1.py>}

But if you do:

from nested1 import printer

Then your namespace will look like:

{"printer" : <function 'printer'>}


Of course, in this case, the name "printer" in the current namespace is
bound to the same function object as nested1.printer - but the _name_
"printer" is local to your current namespace. If you rebind this name in
the current namespace, it wont affect nested1's namespace.

HTH
 
B

Benjamin Kaplan

I take the example from Mark Lutz's excellent book "Learning Python".

*** In nested1.py  I have:
X=99
def printer(): print X

*** In nested2.py  I have:
from nested1 import X, printer
X=88
printer()

What is amazing is that running nested2.py prints 99 and not 88.

My questions are:

1. Using statement "from" instead of "import" should not create a
namespace, at least that's what I think. However, the printer()
function is able to find 99 which is residing in...  a namespace?

It doesn't create a namespace. But printer is still in nested1. When
you do a "from ... import ...", the objects are imported into the
current namespace. However, they are different names for what is
currently the same object. They still follow Python's object
semantics. Here's a simplified overview of what happens

you run nested2.py

1 namespace: nested2, nothing in it (except for the special stuff)

you run "from nested1 import X, printer". This executes everything in
nested1 (because def and class are just executable statements in
Python) and binds X and printer in nested2 to the objects in nested1.
Note that these are now different names for the same objects.

nested1: X = 99, printer = <function in nested1>
nested2: X = 99 printer = <function in nested1>

you call X = 88. Because you are rebinding the object, this name
(nested2.X) is the only one that gets changed. Rebinding doesn't touch
the object in nested1.

nested1: X=99, printer = <function in nested1>
nested2: x=88 printer = <function in nested1>

Notice how the name "printer" in nested2 still refers to an object in
nested1. It is simply another reference, not a new object. When you
call printer, it's still sitting in nested1 and only sees nested1's X.
2. I have tried to access the 88 by qualification from nested2.py.
However, I cannot. If using "print nested1.X" in nested2.py I get an
error

that's because when you do "from ... import ..." it doesn't import the
module itself. There's a totally different behavior between from ...
import and import. Here's what you're trying to do

nested2.py :

import nested1

nested1.X = 88
nested1.printer()
3. Mark says: The from statement is really an assignment to names in
the importer's scope--a name-copy operation, not a name aliasing.   I
don't fully understand what he means. Could anybody explain?

Like I showed before, when you change the unqualified "X" in nested2,
the X in nested1 doesn't change. Using from import is identical to
doing something like this

a = 1
b = a
b = 5
a == 1 #True

a is a name that temporarily referred to the same object as a.
However, when you reassign b, it makes the name "b" refer to a
different object. It doesn't change the object that a and b both refer
to. When you import using from ... import, you end up with 2
different names that, at the start refer to the same object. Mutation
(if you're using a mutable object) will show up in both namespaces,
since they are referring to the same object, but assignment does not.
 
V

vsoler

It doesn't create a namespace. But printer is still in nested1. When
you do a "from ... import ...", the objects are imported into the
current namespace. However, they are different names for what is
currently the same object. They still follow Python's object
semantics. Here's a simplified overview of what happens

you run nested2.py

1 namespace: nested2, nothing in it (except for the special stuff)

you run "from nested1 import X, printer". This executes everything in
nested1 (because def and class are just executable statements in
Python) and binds X and printer in nested2 to the objects in nested1.
Note that these are now different names for the same objects.

nested1: X = 99, printer = <function in nested1>
nested2: X = 99 printer = <function in nested1>

you call X = 88. Because you are rebinding the object, this name
(nested2.X) is the only one that gets changed. Rebinding doesn't touch
the object in nested1.

nested1: X=99, printer = <function in nested1>
nested2: x=88 printer = <function in nested1>

Notice how the name "printer" in nested2 still refers to an object in
nested1. It is simply another reference, not a new object. When you
call printer, it's still sitting in nested1 and only sees nested1's X.


that's because when you do "from ... import ..." it doesn't import the
module itself. There's a totally different behavior between from ...
import and import. Here's what you're trying to do

nested2.py :

import nested1

nested1.X = 88
nested1.printer()




Like I showed before, when you change the unqualified "X" in nested2,
the X in nested1 doesn't change. Using from import is identical to
doing something like this

a = 1
b = a
b = 5
a == 1 #True

a is a name that temporarily referred to the same object as a.
However, when you reassign b, it makes the name "b" refer to a
different object. It doesn't change the object that a and b both refer
to. When you import using  from ... import, you end up with 2
different names that, at the start refer to the same object. Mutation
(if you're using a mutable object) will show up in both namespaces,
since they are referring to the same object, but assignment does not.

I appreciate the preciseness and clearness of your explanations. Thank
you very much indeed.

Vicente Soler
 
S

Steven D'Aprano

2009/12/7 vsoler <[email protected]>: [...]
If you do "from blah import" the imported module itself isn't bound to
any name in the importing module - you can't get at it at all.

Not quite -- you can get to it if you're willing to do some more work.
<module 'math' from '/usr/local/lib/python3.0/lib-dynload/math.so'>


Alternatively, you can fetch it from sys.modules directly, but that's
probably an implementation-specific trick.



I'm not sure what Mark means by that either. It certainly isn't a copy
operation, it doesn't duplicate the object you imported. I don't know
what he means by aliasing, but if he means what I mean by aliasing, then
I'd say the from statement *is* an aliasing operation: it creates a new
name that refers to an existing object found by name.


from module import name

is roughly equivalent to:

import module
name = module.name
del module
 
S

Simon Brunning

2009/12/7 Steven D'Aprano said:
Not quite -- you can get to it if you're willing to do some more work.

"A little inaccuracy sometimes saves tons of explanation." - Saki, The
Square Egg, 1924
 
A

Aahz

I'm not sure what Mark means by that either. It certainly isn't a copy
operation, it doesn't duplicate the object you imported. I don't know
what he means by aliasing, but if he means what I mean by aliasing, then
I'd say the from statement *is* an aliasing operation: it creates a new
name that refers to an existing object found by name.

from module import name

is roughly equivalent to:

import module
name = module.name
del module

The reason why Mark made his comment (although I think it needs some
rephrasing):

import module
from module import name
name = 'foo'
print module.name is name

(Of course this is all completely obvious to anyone who understands
Python's name/binding semantics, but someone just learning about module
imports is probably not in that category and needs some kind of warning
about re-assigning names created by ``from ... import``.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,782
Latest member
ThomasGex

Latest Threads

Top