微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在另一个模块中定义的上下文管理器中使本地函数显示为全局

如何解决在另一个模块中定义的上下文管理器中使本地函数显示为全局

我有一个 Python 单例类,它的实例是这样使用的:

instance = class_with_internal_functionality()
instance.func1()
instance.func2()
instance.func3()

几乎普遍情况下,实例会以各种顺序调用其各种方法来改变其内部状态,有时多达十几次。此外,实例始终用作单例。永远不会同时有两个不同的 class_with_internal_functionality 实例。

简而言之,我试图找到一种方法来用下面的内容替换上面的代码段,而不会一遍又一遍地重复 instance。此外,如果方法名称在 with- 语句之前已经在全局范围内定义,我们应该只是暂时覆盖它们,直到块结束。

with class_with_internal_functionality() as instance:
    func1()
    func2()
    func3()

这是我的第一次尝试,如果 class_with_internal_functionality 与块在同一个模块中定义,那么效果非常好。

class class_with_internal_functionality:
    def __init__(self):
        self.defined_globals = dict()
        self.local_methods = ['func1']

    def __enter__(self):
        """Functionality necessary to use the construction as a context manager.
        This makes an instance's methods available as "global" within the context."""
        print('entering')
        for method_name in self.local_methods:
            # If method_name is defined globally,stash its deFinition away until after we exit.
            if method_name in globals():
                self.defined_globals[method_name] = globals()[method_name]
            # Replace the global deFinition with our local deFinition
            globals()[method_name] = self.__getattribute__(method_name)

    def __exit__(self,*args,**kwargs):
        print('exiting')
        for method_name in self.local_methods:
            # If method_name was prevIoUsly defined before the with-statement,we need to replace it when we leave
            if method_name in self.defined_globals:
                globals()[method_name] = self.defined_globals[method_name]
            else:
                del globals()[method_name]

    def func1(self):
        print('I am inside func1 inside the manager')


def func1():
    print('I am the global function')


if __name__ == '__main__':
    func1()
    print(f'{func1=}')
    instance = class_with_internal_functionality()
    with instance:
        func1()
        print(f'{func1=}')
    func1()
    print(f'{func1=}')

当 with 语句与类在同一个模块中时,这完全按预期工作,具有以下(期望和预期)输出

I am the global function
func1=<function func1 at 0x112c039d0>
entering
I am inside func1 inside the manager
func1=<bound method class_with_internal_functionality.func1 of <__main__.class_with_internal_functionality object at 0x112c11280>>
exiting
I am the global function
func1=<function func1 at 0x112c039d0>

当它在另一个模块中定义并导入时,输出非常不同:

I am the global function
func1=<function func1 at 0x12103e430>
entering
I am the global function
func1=<function func1 at 0x12103e430>
exiting
I am the global function
func1=<function func1 at 0x12103e430>

我发现这种差异是由 globals() 函数仅在模块范围内工作造成的。因此,当从另一个模块导入类时,它确实确实改变了全局变量,但仅在导入模块的上下文中,而不是在主模块的上下文中。因此,main 中的全局变量实际上从未进行过调整,因此该函数从未被覆盖。

当从另一个模块导入上下文管理器类时,有没有办法完成同样的行为?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?