Where is my namespace?

Discussion in 'Python' started by vsoler, Dec 7, 2009.

  1. vsoler

    vsoler Guest

    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
    vsoler, Dec 7, 2009
    #1
    1. Advertising

  2. 2009/12/7 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?


    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.
    Simon Brunning, Dec 7, 2009
    #2
    1. Advertising

  3. 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
    Bruno Desthuilliers, Dec 7, 2009
    #3
  4. On Mon, Dec 7, 2009 at 11:10 AM, vsoler <> 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
    >
    Benjamin Kaplan, Dec 7, 2009
    #4
  5. vsoler

    vsoler Guest

    On Dec 7, 5:39 pm, Benjamin Kaplan <> wrote:
    > On Mon, Dec 7, 2009 at 11:10 AM, vsoler <> 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
    vsoler, Dec 7, 2009
    #5
  6. On Mon, 07 Dec 2009 16:25:39 +0000, Simon Brunning wrote:

    > 2009/12/7 vsoler <>:

    [...]
    > 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
    Steven D'Aprano, Dec 7, 2009
    #6
  7. 2009/12/7 Steven D'Aprano <>:
    > 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.
    Simon Brunning, Dec 7, 2009
    #7
  8. vsoler

    Aahz Guest

    In article <00a7037c$0$15659$>,
    Steven D'Aprano <> wrote:
    >> 2009/12/7 vsoler <>:
    >>>
    >>> 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 () <*> http://www.pythoncraft.com/

    Looking back over the years, after I learned Python I realized that I
    never really had enjoyed programming before.
    Aahz, Dec 20, 2009
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Èý¹â
    Replies:
    1
    Views:
    556
    William F. Robertson, Jr.
    Jul 29, 2003
  2. Replies:
    0
    Views:
    5,110
  3. Anonymous
    Replies:
    3
    Views:
    513
    Ron Natalie
    Aug 18, 2003
  4. Jason Heyes
    Replies:
    1
    Views:
    441
    Woebegone
    Nov 19, 2004
  5. Petter Reinholdtsen
    Replies:
    9
    Views:
    4,340
    Howard
    Nov 29, 2004
Loading...

Share This Page