2

I wonder about why import a variable in python (python 3.4) has different result than importing a module and then referencing, more over why does a deep copy is made - and is there a way to bypass the copy (and not by defining a function that simply returns it)?

a.py

v = 1

def set():
    global v
    v = 3

main.py

import a
import b

a.set()
b.foo()

b.py

from  a import  v

def foo():
    print(v)
    print(a.v)
    print(id(v))
    print(id(a.v))

Output

1
3
1585041872
1585041904
martineau
  • 119,623
  • 25
  • 170
  • 301
Guy L
  • 2,824
  • 2
  • 27
  • 37

4 Answers4

3

The problem is that you're modifying a scalar value. This is not a problem specific to modules, it would work the same when simply passing the variable into a function and modifying it there.

The value 1 is imported from a, period. Whatever you do in a afterwards will not modify the value, because it's a simple immutable scalar value.

If a.v was an object, changes to this object would propagate to any variable holding a reference to it.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • 2
    Just to clarify: changes to the object would propagate, but re-bining the variable to another object would not. – bereal Jun 10 '15 at 14:24
2

Asked a duplicate question myself, and with the help of others I figured out what it is. Here's what I found out. With pydoc links:

from a import v does not add a reference to a.v. Instead, it add a new variable to b as b.v with the value of a.v when import happened. Changing a.v later does not change the value of b.v.

Python 2

The from form does not bind the module name: it goes through the list of identifiers, looks each one of them up in the module found in step (1), and binds the name in the local namespace to the object thus found.

Python 3

The from form uses a slightly more complex process:

  1. find the module specified in the from clause, loading and initializing it if necessary;
  2. for each of the identifiers specified in the import clauses:
    1. check if the imported module has an attribute by that name
    2. if not, attempt to import a submodule with that name and then check the imported module again for that attribute
    3. if the attribute is not found, ImportError is raised.
    4. otherwise, a reference to that value is stored in the local namespace, using the name in the as clause if it is present, otherwise using the attribute name

The keyword here is in the local namespace.

Community
  • 1
  • 1
Michael Kim
  • 689
  • 5
  • 20
1

Let's examine the sequence of events:

a.v = 1     # a.py: v = 1
b.v = a.v   # b.py: from a import v
a.v = 3     # a.set()
print(b.v)  # foo(): print(v)
print(a.v)  # foo(): print(a.v)

As you can see, from a import v actually binds b.v to a value from a, and later modification to the original variable don't affect the copy.

bereal
  • 32,519
  • 6
  • 58
  • 104
0

When you say import a, you are creating a reference to the module. a.v is not copied. I change in one module is noticed in all modules. When you say from a import v you are making a copy of v at the time of the import. If either variable is changed, it is not reflected elsewhere.

Robert Jacobs
  • 3,266
  • 1
  • 20
  • 30