我在使用测试模块中的类方法时遇到全局问题
示例: 我的测试模块的文本:
猫./testmodule.py
class testclass(object):
def __init__(self):
self.testfunc()
def testfunc(self):
print(' '.join(globals()).split(' '))
我的测试课的文本相同:
class testclass(object):
def __init__(self):
self.testfunc()
def testfunc(self):
print(' '.join(globals()).split(' '))
我的测试函数的文本,没什么新意:
def testfunc():
print(' '.join(globals()).split(' '))
然后去测试一下。
Python 3.6.6 (default, Aug 13 2018, 18:24:23)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa='a'
>>>
>>> import testmodule
>>>
>>> class testclass(object):
... def __init__(self):
... self.testfunc()
...
... def testfunc(self):
... print(' '.join(globals()).split(' '))
...
>>> def testfunc():
... print(' '.join(globals()).split(' '))
一切准备就绪,我们来测试一下吧
>>> testfunc()
['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'testmodule', 'testclass', 'testfunc']
变量存在
>>> testclass.testfunc(testclass)
['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'testmodule', 'testclass', 'testfunc']
结果相同,存在变量
>>> testmodule.testclass.testfunc(testclass)
['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__file__', '__cached__', '__builtins__', 'testclass']
>>>
变量丢失。
如何从 testmodule 获得与 testclass 和 testfunc 相同的结果?
扩展@chepner的评论:
globals()
仅返回当前模块的模块级变量。
testfunc()
时,它被定义为 __main__.testfunc
并且调用 globals()
本质上返回 __main__.__dict__
。testmodule
中定义时,它被定义为 testmodule.testfunc
并且 globals()
返回 testmodule.__dict__
。如果您希望
testfunction
访问另一个模块的全局变量,则需要确保在该模块的词法范围内调用 globals()
。最简单的方法是扩展 testfunction
以期望字典作为参数:
## testmodule.py
def testfunc(globals_):
print(globals_)
## REPL or other module
import testmodule
testmodule.testfunc(globals())
__main__
。您需要import __main__
才能使用它。但是你可以从变量__main__
中看到当前模块被命名为__name__
。
当您运行
python somescript.py
时,文件的内容将作为 __main__
模块执行,而不是作为 somescript
模块执行。
Python 有闭包,模块内的函数的行为本质上类似于模块范围内的闭包——所以我希望
globals()
成为每个模块的成员。那么以下将产生预期的结果:
%% testmodule.py
def testfunc(globals_):
print(_globals())
%% REPL
import testmodule
testmodule.testfunc(globals)
但同样,这仅返回测试模块的全局变量。相反,
globals
仅在__builtin__
中定义,并且似乎使用调用者的范围作为隐藏参数。结果是:
## REPL
import testmodule
testmodule.testfunc(globals) # prints testmodule.__dict__
testmodule.testfunc(lambda: globals()) # prints __main__.__dict__
通常期望
f
和 lambda: f()
具有相同的结果。
您不能依赖
somemodule.__dict__
来定义。当您导入模块时,模块实际上可能会选择返回一些包装器对象而不是普通模块对象。实际上,没有任何东西强制 somemodule
具有典型的模块语义!例如。尝试该模块:
## somemodule.py -- Please don't actually do this.
import sys
sys.modules["somemodule"] = "not a module"
## REPL
>>> import somemodule
>>> somemodule
'not a module'
此类更改的现实示例是
os.path
:
>>> import os.path
>>> os.path
<module 'ntpath' from 'C:\tools\msys64\mingw64\lib\python2.7\ntpath.pyc'>