在类级代码中使用字典理解的Python范围问题

时间:2014-04-01 14:36:54

标签: python json csv scoping

最小例子

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})

我想理解为什么这个范围问题正在发生,如果我想做一些疯狂的事情,那么最好的方法就是这样做。我的感觉是第一个代码片段应该按原样运行,但当然不是。

目标

我正在为一些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

它不漂亮,但现在可以使用

1 个答案:

答案 0 :(得分: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)