我为自己的代码麻烦而感到有趣。
...
class Planet:
ATMOSPHERE_GASES = {
'N2':(67.59, 28.0134),
'O2':(28.04, 31.9988),
'CO2':(0.0114, 44.00995),
'CH4':(0.00015, 16.04303),
'Ar':(1.105, 39.948),
'Ne':(1.003, 20.179),
'He':(0.719, 4.0026),
'Kr':(0.45, 83.80),
'H2':(0.001, 2.01594),
'Xe':(0.23, 131.30)}
ATMOSPHERE_GASES['Other'] = tuple([100-sum([x[0] for x in ATMOSPHERE_GASES.values()]), sum([x[1] for x in ATMOSPHERE_GASES.values()])/len(ATMOSPHERE_GASES.values())])
ATMOSPHERE_GASES_MOLAR_MASS = sum([sum(ATMOSPHERE_GASES[x]) for x in ATMOSPHERE_GASES.keys()])/100
...
ATMOSPHERE_GASES_MOLAR_MASS提供错误NameError("name 'ATMOSPHERE_GASES' is not defined",)
我检查了缩进的块,制表符和其他一些原因,尝试重写此部分,但什么也没有。但如果没有上课,它就可以工作!
Traceback (most recent call last):
File "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Extensions\Microsoft\Python\Core\ptvsd_launcher.py", line 111, in <module>
vspd.debug(filename, port_num, debug_id, debug_options, run_as)
File "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd\debugger.py", line 36, in debug
run(address, filename, *args, **kwargs)
File "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd\_main.py", line 47, in run_file
run(argv, addr, **kwargs)
File "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd\_main.py", line 98, in _run
_pydevd.main()
File "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd\pydevd\pydevd.py", line 1628, in main
globals = debugger.run(setup['file'], None, None, is_module)
File "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd\pydevd\pydevd.py", line 1035, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd\pydevd\_pydev_imps\_pydev_execfile.py", line 25, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "C:\Users\Rain0Ash\source\repos\A\A\A.py", line 57, in <module>
class Planet:
File "C:\Users\Rain0Ash\source\repos\A\A\A.py", line 70, in Planet
ATMOSPHERE_GASES_MOLAR_MASS = sum([mult(ATMOSPHERE_GASES[x]) for x in ATMOSPHERE_GASES.keys()])/100
File "C:\Users\Rain0Ash\source\repos\A\A\A.py", line 70, in <listcomp>
ATMOSPHERE_GASES_MOLAR_MASS = sum([mult(ATMOSPHERE_GASES[x]) for x in ATMOSPHERE_GASES.keys()])/100
NameError: name 'ATMOSPHERE_GASES' is not defined
答案 0 :(得分:2)
答案 1 :(得分:2)
这是一个范围界定问题。 Python中的类级变量总是有点奇怪,但是重要的是要了解如果您大量使用它们,它们是如何工作的。
实际的问题是列表理解,它试图将ATMOSPHERE_GASES
作为全局变量进行访问。要了解原因,您需要更多地了解解释器构建的类。要找到问题,我们首先需要使用ast
。这将允许获取抽象语法树,它是一种数据结构。然后,我们将能够使用内置的compile
函数将其转换为字节码对象。
tree = ast.parse('''
<your code here...>
''')
# You need a filename, so we will just use __name__ because it's not important for our purpose
# The 'exec' is to tell the interpreter we want to execute a module, not evaluate an expression
code = compile(tree, __name__, 'exec')
然后,我们将需要使用Python反汇编模块dis
。函数dis.dis
将使您看到代码被编译成什么。它打印出很多代码,但我将其限制为与列表理解相关的代码(列表理解和生成器表达式具有它们自己的代码对象,例如函数和模块)。
>>> dis.dis(code)
...
Disassembly of <code object <listcomp> at 0x00000290AA0D59C0, file "__main__", line 4>:
4 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 16 (to 22)
6 STORE_FAST 1 (x)
8 LOAD_GLOBAL 0 (sum)
10 LOAD_GLOBAL 1 (ATMOSPHERE_GASES)
12 LOAD_FAST 1 (x)
14 BINARY_SUBSCR
16 CALL_FUNCTION 1
18 LIST_APPEND 2
20 JUMP_ABSOLUTE 4
>> 22 RETURN_VALUE
如果您注意索引10上的说明,您会注意到它说LOAD_GLOBAL 1 (ATMOSPHERE_GASES)
。这意味着它将在全局范围而不是类级别范围中寻找ATMOSPHERE_GASES
。
ATMOSPHERE_GASES_MOLAR_MASS = sum(sum(tup) for tup in ATMOSPHERE_GASES.values()) / 100
解决方案起作用的原因是因为您可以避免引起问题的ATMOSPHERE_GASES[x]
逻辑。
TL; DR :由于类作用域变量的方式,类级别的变量很复杂。列表推导认为ATMOSPHERE_GASES
是一个全局变量,然后在模块的全局范围内找不到它。最好将这种计算超出类的定义,移到全局范围内。