使用类的方法作为上下文管理器可以吗?

发布于 2025-01-18 04:23:40 字数 621 浏览 1 评论 0原文

所以,这里有一个简单的代码:

from contextlib import contextmanager

class A:
    
    def __init__(self): 
        self.a = 1
        return

    @contextmanager
    def a2mode(self):
        self.a = 2
        print(self.a)
        yield
        self.a = 1
        print(self.a)
        return
    
ca = A()
with ca.a2mode() as cm:
    print(ca.a+1)

打印:

2
3
1

基本上,我使用类的方法来创建一个上下文,其中属性 a 的值为 a=2,而不是其通常的值。在此基础上,执行一些利用 a 的修改值的操作。在该上下文中进行操作后,属性在上下文管理器之前重置为其原始值。

这样做可以吗?还是会导致一些不可预见的问题?它有效,但我不确定这是否是“禁止”代码。

谢谢! 最好的,JZ

so, here is a simple code:

from contextlib import contextmanager

class A:
    
    def __init__(self): 
        self.a = 1
        return

    @contextmanager
    def a2mode(self):
        self.a = 2
        print(self.a)
        yield
        self.a = 1
        print(self.a)
        return
    
ca = A()
with ca.a2mode() as cm:
    print(ca.a+1)

which prints:

2
3
1

Basically I am using a method of the class to create a context within which the attribute a has a value a=2, instead of its usual value. Based on that some operations are performed that make use of the modified value of a. After operation within that context, the attribute is reset to its original value before the context manager.

Is this ok to do, or can it lead to some unforeseen issues? It works, but I am not sure whether this is "forbidden" code.

Thanks!
Best, JZ

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情愿 2025-01-25 04:23:40

那应该没事的,但是,如果您要确保a即使上下文管理的块提高,也需要使用,请尝试:最终:

    @contextmanager
    def a2mode(self):
        self.a = 2
        try:
            yield
        finally:
            self.a = 1

另外,如果有更多模式,您需要确保重置为上一个模式...

    @contextmanager
    def a2mode(self):
        old_a = self.a
        self.a = 2
        try:
            yield
        finally:
            self.a = old_a

That should be fine, though if you want to ensure a gets reset even if the context-managed block raises, you'll want to use try: finally:.

    @contextmanager
    def a2mode(self):
        self.a = 2
        try:
            yield
        finally:
            self.a = 1

Also, if there would be more modes, you'd want to make sure to reset to the previous mode...

    @contextmanager
    def a2mode(self):
        old_a = self.a
        self.a = 2
        try:
            yield
        finally:
            self.a = old_a
贪恋 2025-01-25 04:23:40

显式定义 __enter____exit__ 可能会更简单,因为 __exit__ 接收 with 语句中引发的任何异常作为一个论点。

class A:
    
    def __init__(self): 
        self.a = 1
        return

    def __enter__(self):
        self.a = 2
        print(self.a)

    def __exit__(self, *args):
        self.a = 1
        print(self.a)
        # I don't know the most idiomatic way of checking this...
        if args != (None, None, None):
            exc_type, exc_value, traceback = args
            ...
            # Return a true value to prevent the exception from propagating

It might be simpler to just define __enter__ and __exit__ explicitly, as __exit__ receives any exception raised in the with statement as an argument.

class A:
    
    def __init__(self): 
        self.a = 1
        return

    def __enter__(self):
        self.a = 2
        print(self.a)

    def __exit__(self, *args):
        self.a = 1
        print(self.a)
        # I don't know the most idiomatic way of checking this...
        if args != (None, None, None):
            exc_type, exc_value, traceback = args
            ...
            # Return a true value to prevent the exception from propagating
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文