Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.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中具有列表理解功能的嵌套上下文管理器_Python_Generator_List Comprehension_Contextmanager - Fatal编程技术网

python中具有列表理解功能的嵌套上下文管理器

python中具有列表理解功能的嵌套上下文管理器,python,generator,list-comprehension,contextmanager,Python,Generator,List Comprehension,Contextmanager,假设我有两个不纯函数-f和j。 j生成一个批次中的项目列表,f生成一个批次列表。他们两个都有一些清理工作要做 我需要做的是,在为f和j进行清理时,为客户机代码提供扁平化的项目列表。一种方法是使用生成器和for循环在屈服后进行清理,但我不喜欢这种方法,因为在这种情况下不明确存在清理 所以我找到了一种方法,通过使用包装器函数(在这段代码中称为dumb) 印刷品 before f before j after j 0 1 2 before j after j 3 4 5 before j after

假设我有两个不纯函数-f和j。 j生成一个批次中的项目列表,f生成一个批次列表。他们两个都有一些清理工作要做

我需要做的是,在为f和j进行清理时,为客户机代码提供扁平化的项目列表。一种方法是使用生成器和for循环在屈服后进行清理,但我不喜欢这种方法,因为在这种情况下不明确存在清理

所以我找到了一种方法,通过使用包装器函数(在这段代码中称为
dumb

印刷品

before f
before j
after j
0
1
2
before j
after j
3
4
5
before j
after j
6
7
8
after f

编辑1。它实际上不起作用,因为它在值实际被消耗之前在j之前和j之后进行。

我想说,在这一点上,您已经超过了
@contextmanager
装饰器,是时候编写您自己的上下文管理器类了

from contextlib import contextmanager

xs = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

@contextmanager
def j(index):
    """Same as before. This is a simple context manager."""
    print("j init")
    yield xs[index]
    print("j cleanup")

def _real_f(the_xs):
    """Mostly the same as before. However, any share state created in the 
    init phase should be passed as an argument. As an example I pass in xs."""
    for i in range(len(the_xs)):
        # can now use explicit with statements for j
        with j(i) as it:
            for item in it:
                yield item

class f(object):
    """f is now replaced by a class that can create contexts for the real
    f to work with"""
    def __enter__(self):
        """Init phase. 
        State required by the real f should be passed as an argument (I
        pass in xs)."""
        print("f init")
        return _real_f(xs)

    def __exit__(self, exception_type, exception, traceback):
        """Clean up phase. 
        Called at end of block. With any details of any exception that
        may have occured in the with block. Return a truthful value to 
        swallow the exception. Can raise your own exception if there is a 
        problem in the clean up phase."""
        print("f clean up")

with f() as it:
    for item in it:
        print(item)

好的,这是可行的,有没有机会用一行
和j(i)来解决这个问题:对于其中的项:产生项
?不确定这与您的显式清理要求有什么关系。
from contextlib import contextmanager

xs = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

@contextmanager
def j(index):
    """Same as before. This is a simple context manager."""
    print("j init")
    yield xs[index]
    print("j cleanup")

def _real_f(the_xs):
    """Mostly the same as before. However, any share state created in the 
    init phase should be passed as an argument. As an example I pass in xs."""
    for i in range(len(the_xs)):
        # can now use explicit with statements for j
        with j(i) as it:
            for item in it:
                yield item

class f(object):
    """f is now replaced by a class that can create contexts for the real
    f to work with"""
    def __enter__(self):
        """Init phase. 
        State required by the real f should be passed as an argument (I
        pass in xs)."""
        print("f init")
        return _real_f(xs)

    def __exit__(self, exception_type, exception, traceback):
        """Clean up phase. 
        Called at end of block. With any details of any exception that
        may have occured in the with block. Return a truthful value to 
        swallow the exception. Can raise your own exception if there is a 
        problem in the clean up phase."""
        print("f clean up")

with f() as it:
    for item in it:
        print(item)