2014-04-01 19 views
6

小例子Python的作用域问题与内部类级代码字典解析

class foo: 
    loadings = dict(hi=1) 
    if 'hi' in loadings: 
     print(loadings['hi']) 
     # works 
     print({e : loadings[e] for e in loadings}) 
     # NameError global name 'loadings' not defined 

我想引用类的命名空间,以及,但不工作或者

class foo: 
    loadings = dict(hi=1) 
    if 'hi' in loadings: 
     print(loadings['hi']) 
     #works 
     print({e : foo.loadings[e] for e in foo.loadings}) 
     #NameError: name 'foo' is not defined 

当然还有,这按预期工作

class foo: 
    loadings = dict(hi=1) 
    if 'hi' in loadings: 
     print(loadings['hi']) 

print({e : foo.loadings[e] for e in foo.loadings}) 

我w蚂蚁了解为什么这个范围问题正在发生,那么,如果我正在尝试做一些疯狂的事情,那么理解最好的方式就是去做。我的感觉是,第一个代码片段应该像现在这样工作,但当然不是。

目标

我用罐装数据库查询一起创建一些CSV/JSON文件DataManager类/模块,一站式我的程序和获取数据。有一些静态数据和一些动态数据,所以它看起来像是在同一个类中很好地使用了静态和非静态数据成员。虽然我明白这些可能是模块级别的变量,但我喜欢拥有静态类数据成员的概念(可能是因为Java的偏见)。任何帮助深表感谢

我的解决方案(现在)

我最终扬起列表理解停留在类范围,在它上面会变成这样的事情

class foo: 
    loadings = dict(hi=1) 
    temp = dict() 
    for e in loadings: 
     temp[e] = loadings[e] # keep in mind this is a minimal example, I probably wouldn't do (just) this 
    print(temp) # works 
    del temp 

这是不漂亮,但它的工作原理现在

+0

你应该做的一切,一个初始化函数内部.... –

+0

我认为它也是有趣的是,'打印({K:v对于k,v in loadings.items()})''确实有效。所以'加载'至少在dict理解中是可见的 – cmd

+0

这不是在init函数中完成的,因为这是一次加载的类的静态数据。我可以有一些像'runonce'这样的标志,但是似乎有一些类级代码是有原因的。 – user25064

回答

4

Name and Binding docs

在类块中定义的名称范围仅限于类 块;它不扩展到方法的代码块 - 这个 包括理解和生成器表达式,因为它们是使用函数作用域实现的 。这意味着,下面将 失败:

class A: 
    a = 42 
    b = list(a + i for i in range(10)) 

详情请参阅this answer


在Python2,可以使用列表理解,因为他们不使用的功能范围实施:

dict([(e,loadings[e]) for e in loadings]) 

但是,如果在Python3运行这段代码将打破。因此,这里是一个替代的解决方法这将在Python2和Python3工作:

class Foo: 
    def loadings(): 
     load = dict(hi=1) 
     if 'hi' in load: 
      print(load['hi']) 
      print({e:load[e] for e in load}) 
     return load 
    loadings = loadings() 

print(Foo.loadings) 
+0

非常感谢,为了一个清晰简洁的解释!我想告诉你,我的意图是用'print(Foo.loadings)'来代替上一个代码块的最后两行,并将它用作静态数据成员。 – user25064