Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何从with语句返回有趣的值?_Python_With Statement_Contextmanager - Fatal编程技术网

Python 如何从with语句返回有趣的值?

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()

有没有比使用globals更好的方法从上下文管理器中获取有趣的值

@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
。您会在哪里增加错误和成功计数?在上下文管理器内部还是外部?