Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Where is my namespace?

Reply
Thread Tools

Where is my namespace?

 
 
vsoler
Guest
Posts: n/a
 
      12-07-2009
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
 
Reply With Quote
 
 
 
 
Simon Brunning
Guest
Posts: n/a
 
      12-07-2009
2009/12/7 vsoler <(E-Mail Removed)>:
> 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?

--
Cheers,
Simon B.
 
Reply With Quote
 
 
 
 
Bruno Desthuilliers
Guest
Posts: n/a
 
      12-07-2009
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
 
Reply With Quote
 
Benjamin Kaplan
Guest
Posts: n/a
 
      12-07-2009
On Mon, Dec 7, 2009 at 11:10 AM, vsoler <(E-Mail Removed)> wrote:
> 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.

> Thank you very much for your time.
>
> Vicente Soler
> --
> http://mail.python.org/mailman/listinfo/python-list
>

 
Reply With Quote
 
vsoler
Guest
Posts: n/a
 
      12-07-2009
On Dec 7, 5:39*pm, Benjamin Kaplan <(E-Mail Removed)> wrote:
> On Mon, Dec 7, 2009 at 11:10 AM, vsoler <(E-Mail Removed)> wrote:
> > 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.
>
> > Thank you very much for your time.

>
> > Vicente Soler
> > --
> >http://mail.python.org/mailman/listinfo/python-list

>
>


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

Vicente Soler
 
Reply With Quote
 
Steven D'Aprano
Guest
Posts: n/a
 
      12-07-2009
On Mon, 07 Dec 2009 16:25:39 +0000, Simon Brunning wrote:

> 2009/12/7 vsoler <(E-Mail Removed)>:

[...]
> 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.

>>> from math import sin
>>> mod = __import__(sin.__module__)
>>> mod

<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.



>> 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?


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



--
Steven
 
Reply With Quote
 
Simon Brunning
Guest
Posts: n/a
 
      12-07-2009
2009/12/7 Steven D'Aprano <(E-Mail Removed)>:
> On Mon, 07 Dec 2009 16:25:39 +0000, Simon Brunning wrote:
>> 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.


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

--
Cheers,
Simon B.
 
Reply With Quote
 
Aahz
Guest
Posts: n/a
 
      12-20-2009
In article <00a7037c$0$15659$(E-Mail Removed)>,
Steven D'Aprano <(E-Mail Removed)> wrote:
>> 2009/12/7 vsoler <(E-Mail Removed)>:
>>>
>>> 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?

>
>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``.)
--
Aahz ((E-Mail Removed)) <*> http://www.pythoncraft.com/

Looking back over the years, after I learned Python I realized that I
never really had enjoyed programming before.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments