2014-03-13 117 views
0

类变量本质上是全局变量吗?Python类变量的范围?

考虑这个例子,在bar.py:

class Bar(object): 
    b = {} 

然后在foo.py:

def foo1(): 
    import bar 
    bar.Bar.b["key"] = "foo1" 


def foo2(): 
    import bar 
    print bar.Bar.b.get("key", "foo2") 

foo1() 
foo2() 

“密钥” 值是坚持 “foo1”。

就我的目的而言,这看起来像一个全局变量。但是为什么在foo1和foo2的调用之间没有重置或删除类变量?

+0

@mgilson我在问为什么两个调用之间没有收集垃圾变量;该链接似乎在谈论实例和类变量之间的差异。 –

回答

3

这是一个类属性。在你的情况下,字典绑定到类Bar。每次输入bar时,都会得到相同的类bar.Bar(毕竟它在bar的全局命名空间中),因此,您将得到相同的字典bar.Bar.b

如果希望每个Bar情况下有不同的字典,你需要做一个实例:

class Bar(object): 
    def __init__(self): 
     self.b = {} 

然后:

def foo1(): 
    import bar 
    bar.Bar().b["key"] = "foo1" 


def foo2(): 
    import bar 
    print bar.Bar().b.get("key", "foo2") 

foo1() 
foo2() 

至于为什么模块bar没有被垃圾收集,当你导入一些东西时,python存储对该模块的引用(参见sys.modules)。下次您导入该模块时,python会从sys.modules中挑选适当的项目,并为您提供参考。这有几个原因。

  • 效率 - 为什么重新评估您已经评估过的代码?
  • 理智的行为

想象具有特殊价值的模块:

# mod.py 
CONSTANT = object() 

现在要使用在foo.pybar.py

# bar.py 
import mod 
def bar(): 
    return mod.CONSTANT 

# foo.py 
import mod 
import bar 
if bar.bar() is mod.CONSTANT: 
    do_something() 

如果导入没有缓存,然后mod.CONSTANT可以foo是不同的,在bar这将是非常令人吃惊的。

+0

谢谢。我担心它被垃圾收集,因为没有明确的参考。 bar的全局名称空间何时被删除?在python关机过程中? –

+0

@ E.Beach - 啊,我现在明白你的问题了(以及本地进口功能的原因)。我编辑过 – mgilson