【问题标题】:In python is there a way to make a function/class that behaves like a function and a context manager?在 python 中,有没有办法制作一个行为像函数和上下文管理器的函数/类?
【发布时间】:2018-07-14 18:29:37
【问题描述】:

在 python 中,有没有办法让函数/类表现得像函数和上下文管理器?

注意:我需要该函数/类来返回一个没有__exit__ 方法的对象,并且我无法更改该对象(这就是我包装它的原因)。

所以仅仅用__enter____exit__ 来创建一个类是行不通的,因为我需要它也像一个函数一样工作。

我已经尝试过contextmanager 装饰器:

@contextmanager
def my_context_man(my_str):
    my_str = 'begging ' + my_str
    yield my_str+' after func'
    print('end')

它在上下文管理器中完美运行,但不是作为函数:

a = 'middle'
old_a = my_context_man(a)
print('old_a', old_a)

with my_context_man(a) as new_a:
    print('new_a', new_a)

输出:

old_a <contextlib._GeneratorContextManager object at 0x0000000004F832E8>
new_a begging middle after func
end

而期望的输出将是:

old_a begging middle after func
new_a begging middle after func
end

编辑: 我遇到的具体问题是psycopg2 模块。 我想使用不同的上下文管理器。它返回一个连接对象。

def connect(dsn=None, connection_factory=None, cursor_factory=None, **kwargs):
    *the connection code*    
    return conn

我正在尝试对其进行更改,以便人们能够将它与我的上下文管理器一起使用,但不会破坏代码。 我无法更改 conn 对象

【问题讨论】:

  • 这里有一些XY。类绝对有可能成为上下文管理器和函数。但是你想要达到什么目的还不清楚。
  • 编辑了这个问题,我希望它现在更清楚了。 @StephenRauch
  • 构造上下文管理器会给你一个上下文管理器。然后您可以调用该上下文管理器,或者如果您只是希望它返回一个字符串,也可以这样做。但是你还没有描述你实际上想要做什么。请阅读我之前评论中的 XY 链接。
  • 不清楚您是否知道上下文管理器是什么或它的用途。
  • connection 对象自 version 2.5 近 5 年前发布以来就可用作上下文管理器。

标签: python function oop python-decorators contextmanager


【解决方案1】:

您的__new__ 方法没有返回my_context_man 的实例,而是str 的实例,并且str 没有__enter__ 方法。在with 语句中,__enter__ 的返回值与as 之后的名称绑定。你想要的

class my_context_man:
    def __init__(self, my_str):
        self.msg = my_str
        print("beginning " + my_str)

    def __enter__(self):
        return self.msg

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('end') 

【讨论】:

  • 这如何解决我想像函数一样调用它
  • 你 (@StephenRauch) 是对的,但这不是重点。
  • 我什至不知道那是什么意思。上下文管理器只是一个对象,它具有遵循上下文管理器协议的__enter____exit__ 方法。
  • 是的,这就是为什么我最初没有回答这个问题。 OP 在一些更高级的概念方面面临一些挑战。肯定会发生一些 XY 事件。
  • 当然,但我认为应该从头开始定义上下文管理器,而不是使用contextlib.contextmanager,这将是一个好的开始。
猜你喜欢
  • 2021-10-22
  • 1970-01-01
  • 2012-10-23
  • 1970-01-01
  • 2021-06-29
  • 2016-05-22
  • 2020-10-21
相关资源
最近更新 更多