Python 如何从with语句返回有趣的值?
有没有比使用globals更好的方法从上下文管理器中获取有趣的值Python 如何从with语句返回有趣的值?,python,with-statement,contextmanager,Python,With Statement,Contextmanager,有没有比使用globals更好的方法从上下文管理器中获取有趣的值 @contextmanager def transaction(): global successCount global errorCount try: yield except: storage.store.rollback() errorCount += 1 else: storage.store.commit()
@contextmanager
def transaction():
global successCount
global errorCount
try:
yield
except:
storage.store.rollback()
errorCount += 1
else:
storage.store.commit()
successCount += 1
其他可能性:
- 单身汉 有点全球性的
- 元组作为上下文管理器的参数 使功能更针对问题/可重用性更低
- 实例,该实例将特定属性作为上下文管理器的参数保存 与元组问题相同,但更清晰
- 在保存值的上下文管理器末尾引发异常。 真是个坏主意
创建一个类来保存成功和错误计数,并实现
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法。我猜您有自己的类,所以只需在其中添加以下内容:
class transaction:
def __init__(self):
self.errorCount = 0
self.successCount = 0
def __enter__(*args):
pass
def __exit__(self, type, value, traceback):
if type:
storage.store.rollback()
self.errorCount += 1
else:
storage.store.commit()
self.successCount += 1
(type
如果调用contextmanager
后没有异常,则为None)
然后您可能已经在某个地方使用了它,它将调用contextmanager
并运行\uuuuuu exit\uuuu()
代码编辑:正如Eli所评论的,只有在您想重置coutners时才创建新的事务实例
t = transaction()
for q in queries:
with t:
t.execute(q)
“将元组作为上下文管理器的参数
使功能更针对问题/可重用性更低”
错
这使上下文管理器保持状态
如果您没有实现比这更多的东西,那么它将是可重用的
但是,实际上不能使用元组,因为它是不可变的。你需要一些可变的集合。我想到了字典和类定义
因此,建议的实施是
“将特定属性作为上下文管理器的参数保存的实例”
您只需要一个带有两个属性的简单类定义。但是,您的事务状态是有状态的,您需要在某个位置保留状态
class Counters(dict):
SUCCEED= 0
FAIL= 1
def __init__( self ):
self[ self.SUCCEED ]= 0
self[ self.FAIL ]= 0
def increment( self, status ):
self[status] += 1
class Transaction(object):
def __init__( self, worker, counters ):
self.worker= worker
self.counters= counters
def __enter__( self ):
self.counters.status= None
def process( self, *args, **kw ):
status= self.worker.execute( *args, **kw )
self.counters.increment( status )
def __exit__( self ):
pass
counts= Counters()
for q in queryList:
with Transaction(execQuery,counts) as t:
t.process( q )
print counts
如果您说“with transaction()as t:”,那么每次执行with语句及其内容时都会生成一个新的事务。他真的需要一个(可能是全局的)t变量,这样他就可以说“with t:”-1您的
事务类没有\uuuuuuuuuuuuu()
方法,当试图在with
语句中使用AttributeError时(即使没有关联的as
子句),它会引发AttributeError
。对。但是要注意上下文管理器的实时性。使用类属性存储感兴趣的值,这样即使在上下文管理器超出范围后也可以检索它们。与@Ber建议的使用类属性不同,还可以通过实例化上下文管理器并将其绑定到with
语句前面的标识符来解决生存期问题,然后在中使用该标识符。这样,之后上下文管理器对象仍将存在。它还需要一个\uuuu enter\uuuu()
方法,但这只能返回self
。您会在哪里增加错误和成功计数?在上下文管理器内部还是外部?