模块中类的方法看不到我的全局变量()

问题描述 投票:0回答:1

我在使用测试模块中的类方法时遇到全局问题

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

猫./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 相同的结果?

python global
1个回答
2
投票

扩展@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)
    

    但同样,这仅返回测试模块的全局变量。相反,

    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'>
    
© www.soinside.com 2019 - 2024. All rights reserved.