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

use*_*064 6 python csv json 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
Run Code Online (Sandbox Code Playgroud)

我也尝试引用类命名空间,但这也不起作用

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
Run Code Online (Sandbox Code Playgroud)

当然,这可以按预期工作

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

print({e : foo.loadings[e] for e in foo.loadings})
Run Code Online (Sandbox Code Playgroud)

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

目标

我正在为一些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
Run Code Online (Sandbox Code Playgroud)

它不漂亮,但它现在有效

unu*_*tbu 4

根据名称和绑定文档

\n\n
\n

类块中定义的名称范围仅限于 class\n 块;它不会扩展到方法 \xe2\x80\x93 的代码块,这\n 包括推导式和生成器表达式,因为它们是使用函数作用域实现的。这意味着以下操作将失败:

\n\n
class A:\n    a = 42\n    b = list(a + i for i in range(10))\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

有关更多详细信息,请参阅此答案。

\n\n
\n\n

在 Python2 中,可以使用列表推导式,因为它们是在不使用函数作用域的情况下实现的:

\n\n
dict([(e,loadings[e]) for e in loadings])\n
Run Code Online (Sandbox Code Playgroud)\n\n

但如果在 Python3 中运行此代码将会崩溃。因此,这里有一个适用于 Python2 和 Python3 的替代解决方法:

\n\n
class Foo:\n    def loadings():\n        load = dict(hi=1)\n        if \'hi\' in load:\n            print(load[\'hi\']) \n            print({e:load[e] for e in load})\n        return load\n    loadings = loadings()\n\nprint(Foo.loadings)\n
Run Code Online (Sandbox Code Playgroud)\n