Unable to access modified value of imported variable
<p>I am new to python and have some problem understanding the scope here.</p>

<p>I have a python module A with three global variables :</p>

<pre><code>XYZ = "val1"
ABC = {"k1" : "v1", "k2" : "v2"}
PQR = 1

class Cls_A() :
    def sm_fn_A(self) :
        global XYZ
        global ABC
        global PQR

        XYZ = "val2"
        ABC["k1"] = "z1"
        ABC["k3"] = "v3"
        PQR += 1
</code></pre>

<p>And another module B :</p>

<pre><code>from A import Cls_A, XYZ, ABC, PQR

class Cls_B():
    def sm_fn_B(self) :
        Cls_A().sm_fn_A()
        print XYZ
        print ABC
        print PQR

Cls_B().sm_fn_B()
</code></pre>

<p>This gives me the following output :</p>

<pre><code>val1
{'k3': 'v3', 'k2': 'v2', 'k1': 'z1'}
1
</code></pre>

<p>Since these are all global variables, why do I not get updated values of all the global variables printed ? </p>

<h1>Explanation</h1>

<p>Three global variables are defined in module <code>A</code>, in this code:</p>

<pre><code>XYZ = "val1"
ABC = {"k1" : "v1", "k2" : "v2"}
PQR = 1
</code></pre>

<p>Then new global variables <code>XYZ</code>, <code>ABC</code>, <code>PQR</code> are defined in module <code>B</code>, in this code:</p>

<pre><code>from A import Cls_A, XYZ, ABC, PQR
</code></pre>

<p>This line of code creates new variables, just as if the following was written:</p>

<pre><code>import A
XYZ = A.XYZ
ABC = A.ABC
PQR = A.PQR
</code></pre>

<p>It is important to understand that <code>A.XYZ</code> and <code>B.XYZ</code> are two variables which point to the same object. They are not the same variable.</p>

<p>Then a new object is assigned to <code>A.XYZ</code>:</p>

<pre><code>    XYZ = "val2"
</code></pre>

<p>This modified <code>A.XYZ</code>, but did not modify <code>B.XYZ</code>. The two used to be two variables which pointed to the same object, but now <code>A.XYZ</code> points to a different object.</p>

<p>On the other hand, <code>A.ABC</code> is not assiciated with a different object. Instead, the object itself is modified. When the object is modified, both <code>A.ABC</code> and <code>B.ABC</code> still point to the same object:</p>

<pre><code>    ABC["k1"] = "z1"
    ABC["k3"] = "v3"
</code></pre>

<p>The third case is also not a case of object modification, but rather reassignment:</p>

<pre><code>    PQR += 1
</code></pre>

<p>The value was incremented. That created a new object and than thet new object was assigned to <code>A.PQR</code>. <code>B.PQR</code> is unchanged. This is equivalent to:</p>

<pre><code>    PQR = PQR + 1
</code></pre>

<p>A thing which may not be obvious is that both strings and integers are <em>immutable</em> objects in Python (there is no way to change number to <code>2</code> to become <code>3</code> - one can only assign a different int object to a variable, not change the existing one). Because of that, there is actually no way to change <code>A.XYZ</code> in a way that affects <code>B.XYZ</code>.</p>

<h2>The dictionary could behave the same way</h2>

<p>The reason why with the dictionary it <em>"worked"</em> is that the object was modified. If a new dictioanry was assigned to <code>A.ABC</code>, that would not work. E.g.</p>

<pre><code>    ABC = {'k3': 'v3', 'k2': 'v2', 'k1': 'z1'}
</code></pre>

<p>Now it would not affect <code>B.ABC</code>, because the object in <code>A.ABC</code> was not changed. Another object was assigned to <code>A.ABC</code> instead.</p>

<h1>Not related to modules</h1>

<p>The same behaviour can be seen without any modules:</p>

<pre><code>A_XYZ = "val1"
A_ABC = {"k1" : "v1", "k2" : "v2"}
A_PQR = 1

B_XYZ = A_XYZ
B_ABC = A_ABC
B_PQR = A_PQR

A_XYZ = "val2"
A_ABC["k1"] = "z1"
A_ABC["k3"] = "v3"
A_PQR += 1

print B_XYZ
print B_ABC
print B_PQR
</code></pre>

<p>Prints:</p>

<pre><code>val1
{'k3': 'v3', 'k2': 'v2', 'k1': 'z1'}
1
</code></pre>

<h1>Solution</h1>

<p>Well, don't keep reference to the temporary object. Use the variable which has the correct value.</p>

<p>For example, in module <code>B</code>:</p>

<pre><code>import A

class Cls_B():
    def sm_fn_B(self) :
        A.Cls_A().sm_fn_A()
        print A.XYZ
        print A.ABC
        print A.PQR

Cls_B().sm_fn_B()
</code></pre>

<p>Now there is actually no <code>B.XYZ</code> variable, which could be wrong. <code>A.XYZ</code> is always used.</p>

python python-2.7 import scope global-variables