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

时间:2018-12-06 16:15:59

标签: python globals

我使用我的testmodule中的类方法对全局变量有疑问

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

cat ./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']

完美,我看到了我的aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

>>> 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']
>>>

嘿!慢慢来! WTF?变量丢失。

请帮帮我 我如何从testmodule像testclass和testfunc获得相同的结果?

1 个答案:

答案 0 :(得分:0)

扩展@chepner的注释:globals()仅返回当前模块的模块级变量。

  • 在REPL中定义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)
    

    但同样,这仅返回testmodule的全局变量。相反,globals仅在__builtin__中定义,并且似乎将调用方的范围用作隐藏参数。结果:

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

    通常期望flambda: 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'>