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

inkz8wg9  于 2021-08-20  发布在  Java
关注(0)|答案(0)|浏览(144)

我有一个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中的globals永远不会被实际调整,因此该函数永远不会被重写。
当从另一个模块导入上下文管理器类时,是否有方法实现相同的行为?

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题