Reputation: 6768
Why does the following not work:
from sys import ps1
ps1 = 'something else '
but this does?
import sys
sys.ps1 = 'something else '
If I run the simple test
import sys
from sys import ps1
ps1 = 'something else'
sys.ps1 = 'something else'
the first assignment doesn't work, but the second does. the id() for both ps1 and sys.ps1 are the same, so they should refer to the same thing, right?
Upvotes: 2
Views: 622
Reputation: 78823
The amount of confusion that Python's import statement causes should keep its inventors up at night!
Here is a page that attempts to explain import. In particular it describes:
import X imports the module X and you use X.name to refer to name defined in module X
from X import * imports the module X but creates references in the current namespace to all public objects defined in X. You use name to refer to name that's defined in X, but X itself is not defined, so X.name does not work.
One way, perhaps, to look at from X import * is almost as if it inserts the entire source of module X inline and hence you simply use name directly as if it were inline and you cannot use X because it no longer exists.
Note that the practice of importing * from a module or package is frowned upon.
Upvotes: 0
Reputation: 365925
The short version is: Assignment doesn't mutate anything in Python, it just rebinds names. Rebinding a different name, that happens to be currently bound to a reference to the same string as sys.ps1
doesn't affect sys.ps1
in any way.
Let's go through step by step:
from sys import ps1
This imports sys
(but doesn't bind a name sys
in the current globals), then binds the name ps1
in the current globals to the same object as sys
's ps1
.
ps1 = 'something else '
This rebinds the name ps1
in the current globals to the same object as the literal 'something else'
. There's no way that could possibly affect the sys
module.
import sys
This imports sys
, and then binds the name sys
in the current globals to it.
sys.ps1 = 'something else '
This looks up the name sys
in the current globals, getting a reference to the sys
module, then rebinds the name ps1
in that module to the same object as the literal 'something else '
.
Or, putting it in pseudo-Python terms, instead of in English…
Your first code sample is like this:
tempspace._sys = __import__('sys')
globals.ps1 = tempspace._sys.ps1
del tempspace._sys
globals.ps1 = 'something else '
Your second is like this:
globals.sys = sys_modules.sys = __import__('sys')
globals.sys.ps1 = 'something else '
Here is a transcript of what you described in the comments.
Python 2.7.2 (default, Jun 20 2012, 16:23:33)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> from sys import ps1
>>> id(sys.ps1)
4360831168
>>> id(ps1)
4360831168
>>> sys.ps1 = 'something else '
something else ps1
'>>> '
something else
sys.ps1
and ps1
have the same ID, because they are two different names that reference the same object.
And changing sys.ps1
does not change ps1
.
Upvotes: 3