1

This is apparently the same question as this (S.O. didn't find it until later). Am investigating duping. However, the title line alone makes this a useful question.

In the following (two) chunks of code, why don't I get the updated value when I import?

Two files: import.py and export.py Here is export.py:

i=12345

def change_i(x):
  global i
  i=x
  print "export changed i to {0}".format(repr(i))

Here is import.py:

from export import i, change_i

print "Import gets i={0}".format(repr(i))
change_i(5)
print "Import has i={0}".format(repr(i))

Here is the result:

> python import.py 
Import gets i=12345
export changed i to 5
Import has i=12345

Why isn't import.py getting the new value 5????

Community
  • 1
  • 1
Mark Gerolimatos
  • 2,424
  • 1
  • 23
  • 33
  • Yes. But S.O. didn't find that question until you did. So yes it's a duplicate but I would maintain that the secondary search term is useful. There is absolutely no indication that these are the same question from the titles. – Mark Gerolimatos May 08 '17 at 19:06

1 Answers1

0

NOPE. TURNS OUT THIS IS A LIE/MISCONCEPTION.

When you import, you import the current value of the imported symbol and add it to your namespace as defined. You are not importing a reference, you are importing a value.

Thus, to get the updated value of i, you must import a variable that holds a reference to that symbol.

In other words, importing is NOT like an import in JAVA, external declaration in C/C++ or even a use clause in PERL.

Rather, the following statement in Python:

from some_other_module import a as x

is more like the following code in K&R C:

extern int a; /* import from the EXTERN file */

int x = a;

(caveat: in the Python case, "a" and "x" are essentially a reference to the actual value: you're not copying the INT, you're copying the reference address)

This is sneakily defined in the Python language reference: the use of object instead of symbol. I would suggest that the Python language reference make this more clear and less legal.

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.

Mark Gerolimatos
  • 2,424
  • 1
  • 23
  • 33
  • Now try the same with a list. Assign a list to `i` and modify `change_i` to *append* or otherwise modify `i` without changing what `i` is referring to. – vaultah May 08 '17 at 18:49
  • You are just repeating my statement from the beginning of my answer. What's your point? – Mark Gerolimatos May 08 '17 at 18:53
  • Actually, you do import a reference to the same object that is in the other module. No lie, no copy. The thing is, `i=x` _rebinds_ the `i` in your module namespace to a different object. – tdelaney May 08 '17 at 18:53
  • Uhhhh..."...to a different object"...isn't that a copy? Okay, maybe not a byte-for-byte copy: the reference is that which is copied, and the "modify on write" makes for an effective "copy" semantic. – Mark Gerolimatos May 08 '17 at 18:55
  • 1
    @MarkGerolimatos my point is that you have a misconception about how Python references and import system work and so your answer is wrong. You didn't try it with a list, did you? The list gets updated and you can see it changing inside *import.py*, too. – vaultah May 08 '17 at 18:57
  • Ummm @vaultah , you are still misunderstanding my point. I think YOU have the fundamental misconception. Appending to a list keeps the initial reference to the list the same, it just modifies its contents. However, assigning the list (i = [12345] ... i = [5] ), or using Tuples: ( i = (12345,) ... i += 5 ) will produce the same results as shown in the question. – Mark Gerolimatos May 08 '17 at 19:01
  • 1
    Python imports a reference to the object, which is referred to by the variable you're trying to import. Yes, rebinding it to some other object inside the module won't change the reference you imported earlier. Still, technically, Python imports a reference to a value, and this means that your first paragraph is misleading. – vaultah May 08 '17 at 19:19
  • @vaultah If it looks like a duck and quacks like a duck, it's a duck. The end result is that a Python import is like the C-extern statement I made. The basic concept is that you are not importing a SYMBOL, you are importing that symbol's value at time of the import call. REMEMBER that "value" isn't the 1, 2, ['a', 'b', 'c'] value, but rather the reference to the storage that contains 1, 2, ['a', 'b', 'c']. It is VITAL that this be understood, and frankly, it's not that obvious from the documentation. Unlike importing classes funcs and modules, which rarely change, variables DO change – Mark Gerolimatos May 08 '17 at 21:08