Reputation: 766
I have been studying Python for three months and now I have a question that I could not solve by using google, but luckily I am able to simplify it here:
I have a var_class module:
#var_class.py
class A(object):
def __init__(self, x):
self.x = x+2
zz = A(10)
class B():
b = 0
def __init__(self):
pass
def update(self):
B.b = zz.x
and in main program I have:
#main.py
from var_class import *
b_class = B()
b_class.b # I get 0 as expected
zz = A(100)
b_class.update()
b_class.b # Instead of 102, I get 12 unexpectedly
You see my goal is to change "zz" frequently for every data input and then update a class variable 'b', and the reason I wrote zz = A(10) in var_class.py is that otherwise when I import it, module 'var_class' is missing 'zz' in 'class B', it would give error "global name zz is not defined".
However, as I write it like this now, looks like the value '10' is stuck to the class, and I am not able to change it in the main program. Don't know how to overcome this. Thanks in advance for any help.
alKid wrote the whole answer first, have to thanks to alexvassel and Mr. C too, would like to know if there is way to thanks them, others helped me with the knowledge, also appreciate a lot.
Upvotes: 0
Views: 5362
Reputation: 28292
Easy understanding:
You can't do that, you're inside var_class
module, so zz
is A(10)
.
How about passing zz as a parameter? Like this!
class A(object):
def __init__(self, x):
self.x = x+2
zz = A(10)
class B():
b = 0
def __init__(self):
pass
def update(self, zz):
B.b = zz.x
Hope this helps!
Upvotes: 1
Reputation: 12401
when you import a variable from a module, you get a copy of the variable, not the original. you need to write to the original directly.
from a.b import c
from a.b.c import var
a.b.c.var = 1
var = 2
a.b.c.var
1
var
2
Edit: So, more correctly, in python, there are objects in memory, and then there are names for the objects. When you import a module, you create two separate names, but they both point to the same object - i.e. they have a reference to the same object. It's very similar to the below code, which doesn't require any imports at all:
>>> a = 4
>>> b = a
>>> b
4
>>> a
4
>>> b = 'something different'
>>> b
'something different'
>>> a
4
Why did changing b not also change a? The sequence is like this: First, we create an object (the 4) and point the name 'a' at it. Then, we create a name 'b', and we point it at the same object. So, now looking up those names returns the same object. Now, we then go back and point the name 'b' at a different object, a string. The object 'a' is pointing to still exists, and has not changed.
New users more often trip up on this the other way, with objects like lists:
>>> a = [1,2,3,4,5]
>>> b = a
>>> b
[1,2,3,4,5]
>>> a
[1,2,3,4,5]
>>> b.append(6)
>>> b
[1,2,3,4,5,6]
>>> a
[1,2,3,4,5,6]
>>> b = b[1:3]
>>> b
[2,3]
>>> a
[1,2,3,4,5,6]
What's going on here? Well, first we create a list object, and then point the name 'a' at it. Then we create the name 'b' and point it to the same object. So, 'a' and 'b' both point to the same list. Then, we use the reference b to get the object and modify it. Note that we haven't changed what 'b' points to in this case - we grabbed the reference, and then modified the object it points to directly. So, in this case, both 'a' and 'b' will see the change - they both point to the modified object. Then, we extract a slice, and assign it to 'b'. Now, this actually creates a new object, and points 'b' at it - 'b' is no longer pointing to the original object. So now 'a' and 'b' point to different objects, and now updates to one are no longer reflected in the other.
The import case is just a special case of this.
Upvotes: 0
Reputation: 568
python runtime finds variables by namespace. Namespace is something like scope. When B.b = zz.x executes, the runtime first searches the local namespace(the function namespace -- update), it sees no zz. Then, it goes to the module space(var_class), well we get the variable and stop searching.
The python namespace search order:
1. local namespace, the function scope
2. global namespace, the module scope
3. built-in namespace
Better not use global variables around.
your code may like this:
class B():
b = 0
def __init__(self):
pass
def update(self, zz):
B.b = zz.x
Upvotes: 1
Reputation: 297
maybe you can do this
class B():
b = 0
def __init__(self):
pass
def update(self,value):
self.b =self.b+value
Upvotes: -1
Reputation: 5177
That is a matter of scope! you are using zz = A(100) in your main.py. But when you call b_class.update(), b_class has to get "some2 variable called "zz" - and the one which is available is the one you defined in your class.py - and this one still has the value A(10)!!!
To work around this, you have different options.
global
variable and use ist (google "python globals" for more info on this approach).b_class.update(A.x)
. This avoids globals and is more readable. Of course, you'll have to adjust B.update for the new parameter.Upvotes: 0
Reputation: 10740
When you do B.b = zz.x
(update
method) you are inside the module var_class
, so zz
is A(10)
Upvotes: 1