gpt4 book ai didi

python - 防止可以使用 "with"调用的类中的方法被调用两次

转载 作者:行者123 更新时间:2023-12-01 01:56:19 24 4
gpt4 key购买 nike

我正在编写一个可以与 with 语句一起使用的类,如下所示:

with Context() as context:
if context:
...

该类有一个 enter 函数,该函数只能调用一次并返回一个 bool 值。我想防止它被调用两次(例如 with Context().enter() as context):

class Context(object):
def __init__(self):
self.ENTER_HAS_BEEN_CALLED = False

def __enter__(self):
return self.enter()

def __exit__(self):
self.exit()

def enter(self):
"""Do things once and only once
Returns boolean, not self
"""
if self.ENTER_HAS_BEEN_CALLED:
# not sure what to do here, return?
# call self.exit()?

self.ENTER_HAS_BEEN_CALLED = True

# do things that should only be done once
value = True # or False
return value

def exit(self):
pass

这是防止函数被调用两次的正确方法吗?我想要返回值,并且还允许此代码工作:

context_manager = Context()
context = context_manager.enter()
if context: ...
context_manager.exit()

最佳答案

您已经很接近了,但是,如果在使用装饰器设置标志后已经调用了 contextmanager,您可以简单地引发错误。下面的代码编写为 enter__enter__可以按照最初的预期返回单独的变量( Trueself ),并符合 contextmanager 的一般思想:

def control_manager(f):
def wrapper(cls):
if getattr(cls, 'flag'):
raise Exception("Already expended the context manager")
setattr(cls, 'flag', True)
return f(cls)
return wrapper

class Context:
def __init__(self):
self.flag = False
@control_manager
def __enter__(self):
return self
def __exit__(self, *args):
pass
@control_manager
def enter(self):
return True
def exit(self):
#do something
pass

with Context() as f:
v = f.enter()

Traceback (most recent call last): File "", line 2, in File "", line 4, in wrapper Exception: Already expended the context manager

但是,它将在第二次测试中起作用:

c = Context()
v = c.enter()
c.exit()

但是,如果您想使用enter作为类中 contextmanager 的主要 block ,您可以将其视为 classmethodcontextlib.contextmanager :

import contextlib

class Control:
flag = False
def __init__(self):
pass
def __enter__(self):
with Control.enter() as f:
v = f
return self
def __exit__(self, *args):
pass
@classmethod
@control_manager
@contextlib.contextmanager
def enter(cls):
yield True


with Control() as f:
pass
#runs without exception

with Control.enter() as t:
pass

Traceback (most recent call last): File "", line 1, in File "", line 4, in wrapper Exception: Already expended the context manager

关于python - 防止可以使用 "with"调用的类中的方法被调用两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50142921/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com