模块中 class 的方法看不到我的 globals()

Method of class in module doesn't see my globals()

我在使用测试模块

中的class方法时遇到全局问题

示例: 我的测试模块的文本:

猫./testmodule.py

class testclass(object):
    def __init__(self):
        self.testfunc()
    
    def testfunc(self):
        print(' '.join(globals()).split(' '))

我的测试文本class相同:

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() return仅当前模块的模块级变量。

  • 当您在 REPL 中定义 testfunc() 时,它被定义为 __main__.testfunc 并调用 globals() returns 本质上是 __main__.__dict__.
  • 在你的testmodule中定义时,定义为testmodule.testfuncglobals() returns testmodule.__dict__.

如果你想testfunction访问另一个模块的全局变量,你需要确保在模块的词法范围内调用globals()。最简单的是扩展 testfunction 以期望字典作为参数:

## testmodule.py
def testfunc(globals_):
    print(globals)

## REPL or other module
import testmodule
testmodule.testfunc(globals())

其他详细信息

    默认情况下未定义
  • __main__。您需要 import __main__ 才能使用它。但是从变量__name__.
  • 可以看出当前模块的名字是__main__
  • 当您 运行 python somescript.py 时,文件的内容作为 __main__ 模块执行,而不是作为 somescript 模块执行。
  • Python 有闭包,模块内的函数本质上就像模块范围内的闭包——所以我希望 globals() 成为每个模块的成员。那么以下将产生预期的结果:

    %% testmodule.py
    def testfunc(globals_):
        print(_globals())
    
    %% REPL
    import testmodule
    testmodule.testfunc(globals)
    

    但是,这 return 只是测试模块的全局变量。相反 globals 仅在 __builtin__ 中定义,并且似乎使用调用者的范围作为隐藏参数。结果:

    ## REPL
    import testmodule
    testmodule.testfunc(globals) # prints testmodule.__dict__
    testmodule.testfunc(lambda: globals())  # prints __main__.__dict__
    

    通常期望 flambda: f() 具有相同的结果。

  • 你不能依赖somemodule.__dict__来定义。当您导入一个模块时,它实际上可能会选择 return 一些包装器对象而不是普通的模块对象。实际上,甚至没有任何东西强制 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'>