2013-10-09 26 views
0

我一直在学习Python三个月,现在我有一个问题,我无法通过使用谷歌解决,但幸运的是我能够简化它在这里:Python:更新实例的值,并在导入模块的类中使用它

我有一个var_class模块:

#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 

,并在主程序中,我有:

#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 

你看,我的目标是改变“ZZ”经常为每个数据的输入,然后ü更新一个类变量'b',并且我在var_class.py中写入zz = A(10)的原因是否则当我导入它时,模块'var_class'在'B类'中缺少'zz',它会给出错误“全球名称zz未定义”。

但是,现在我写这样,看起来像值'10'卡住了课程,我不能在主程序中更改它。不知道如何克服这一点。 在此先感谢您的帮助。

答:

醇酸第一次写的全部答案,要感谢alexvassel和C先生也想知道是否有办法来感谢他们,别人帮了我的知识,也欣赏许多。

+3

'进口*'是一个不好的做法 – alexvassel

+0

同意,我听说是不推荐,想知道是否改变什么建议吗? @alexvassel – TongZZZ

+0

'from var_class import A,B' – alexvassel

回答

1

容易理解: 你不能做到这一点,你在里面var_class模块,所以zzA(10)

将zz作为参数传递怎么样?喜欢这个!

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 

希望这有助于!

+0

最后一行是B.b = zz.x还是相同?实际上,@alKid – TongZZZ

+0

两者是相同的东西。你不必担心。 – aIKid

+0

不错,你看我不想有zz = A(10),我现在可以删除zz = A(10)吗?有没有办法避免这种情况? @alKid – TongZZZ

1

当你B.b = zz.xupdate法)你是模块var_class里面,所以zzA(10)

+0

这是有帮助的,你可以给我一个替代方式来做我需要的东西吗? – TongZZZ

+2

将参数传递给'update'方法 – alexvassel

0

这是范围的事!您在main.py中使用zz = A(100)。但是当你调用b_class.update()时,b_class必须得到“some2”变量叫做“zz” - 可用的是你在class.py中定义的变量 - 这个变量仍然有值A(10) !

要解决这个问题,你有不同的选择。

  • 的肮脏的黑客(但最接近您的解决方案)将定义一个变量global和使用IST(谷歌“巨蟒全局”为更多关于这个方法的信息)
  • 我建议把A(或者Ax)传递给你的“更新”方法b_class.update(A.x)这样可以避免全局变量并且更具可读性当然,你必须调整B.update新参数。
-1

也许你可以做到这一点

class B(): 
    b = 0  
    def __init__(self): 
     pass 
    def update(self,value): 
     self.b =self.b+value 
+0

-1。传递的值不是整数,而是类A的一个实例 – aIKid

0

当你从一个模块导入一个变量时,你会得到一个拷贝的变量,而不是原来的。你需要直接写入原文。

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 

编辑:所以,更准确地说,在Python中,内存中有对象,然后有对象的名称。当您导入模块时,将创建两个单独的名称,但它们都指向相同的对象 - 即它们具有对同一对象的引用。它非常类似于下面的代码,它根本不需要任何进口:

>>> a = 4 
>>> b = a 
>>> b 
4 
>>> a 
4 
>>> b = 'something different' 
>>> b 
'something different' 
>>> a 
4 

为什么更改b不也改变了?顺序是这样的:首先,我们创建一个对象(4)并将它命名为'a'。然后,我们创建一个名字'b',并且我们将它指向同一个对象。因此,现在查找这些名称返回相同的对象。现在,我们回去并将名字'b'指向一个不同的对象,一个字符串。对象'a'指向仍然存在,并且没有改变。

新用户更经常绊倒在此的其他方式,如列表对象:

>>> 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] 

这是怎么回事?那么,首先我们创建一个列表对象,然后将它命名为'a'。然后我们创建名称'b'并将其指向同一个对象。所以'a'和'b'都指向相同的列表。然后,我们使用引用b来获取对象并对其进行修改。请注意,在这种情况下,我们没有改变'b'指向 - 我们抓住引用,然后修改它直接指向的对象。因此,在这种情况下,'a'和'b'都会看到更改 - 它们都指向修改后的对象。然后,我们提取一个切片,并将其分配给'b'。现在,这实际上创建了一个新的对象,并在其上指向'b' - 'b'不再指向原始对象。所以现在'a'和'b'指向不同的对象,现在更新到另一个不再反映。

导入案例只是一个特例。

1

python运行时通过命名空间查找变量。命名空间就像范围一样。当执行B.b = zz.x时,运行时首先搜索本地名称空间(函数名称空间 - 更新),它看不到zz。然后,它进入模块空间(var_class),我们得到变量并停止搜索。

蟒蛇名字空间的搜索顺序:
1.局部名字空间,功能范围
2.全局命名空间,模块范围
3.内置名字空间

更好绕不使用全局变量。

你的代码可能是这样的:

class B(): 
b = 0  
def __init__(self): 
    pass 
def update(self, zz): 
    B.b = zz.x