Unexpected import behavior, treating integers and lists differently
I have a problem with my program and I was able to reproduce this unexpected (at least unexpected to me) behavior in a small scale so now I'm certain it is not another bug.
Lets say I have 3 python modules: one
, two
and three
.
In three
we have:
var = 0
list = []
So there we have a integer that is equal to zero and and empty list.
In two
we have:
from three import var, list
def funct():
print var*2
print list
return
So we import var
and list
and simply define a function that will print both and return.
Instead of calling funct()
in two
I called it in one
, but not before doing some "operations" to them.
from three import var, list
from two import funct
if 2 < 4:
var += 1
list.append("x")
print funct(开发者_JAVA百科)
So here comes my question.
I never expected this result:
0
['x']
None
How come the x
was added to the list with the append()
and 1 was NOT added to var
, to be clear. I was expecting:
2
['x']
None
If find it very strange that they receive different treatments under the same circumstances.
- Am I missing something here?
- Am I doing something wrong with the imports?
If not:
- Why does it behave like this?
- How should this problem be solved / approached?
Thank in advance.
To "fix" your program, you would have to add "global var", as in:
if 2 < 4:
global var
var += 1
list.append("x")
But this is illegal according to http://docs.python.org/reference/simple_stmts.html#global:
Names listed in a global statement must not be defined as formal parameters or in a for loop control target, class definition, function definition, or import statement.
Then again, following the link above:
CPython implementation detail: The current implementation does not enforce the latter two restrictions, but programs should not abuse this freedom, as future implementations may enforce them or silently change the meaning of the program.
Edit:
The solution is to change:
from three import var, list
to:
from three import list
import three
then don't use global namespace, but specify explicitly the namespace of three (you imported the symbol)
code:
three.var += 1
Make sure two.py and one.py are changed accordingly in their import/from statements
http://docs.python.org/tutorial/modules.html#more-on-modules
Each module has its own private symbol table, which is used as the global symbol table by all functions defined in the module. Thus, the author of a module can use global variables in the module without worrying about accidental clashes with a user’s global variables. On the other hand, if you know what you are doing you can touch a module’s global variables with the same notation used to refer to its functions, modname.itemname.
This is nothing to do with import, and everything to do with the different types involved.
list
is a mutable type. list.append
modifies the object in place, and returns None
.
int
is an immutable type. Its +=
operator returns a new object.
Learn more about mutable and immutable types at the Python documentation of its data model.
Importing a name copies the reference the name contains to your module. In your code, the integer gets rebound, but the list gets mutated. Since the list reference never changes, the original object is mutated. Hence different integer, same list.
精彩评论