python中具有列表理解功能的嵌套上下文管理器
假设我有两个不纯函数-f和j。 j生成一个批次中的项目列表,f生成一个批次列表。他们两个都有一些清理工作要做 我需要做的是,在为f和j进行清理时,为客户机代码提供扁平化的项目列表。一种方法是使用生成器和for循环在屈服后进行清理,但我不喜欢这种方法,因为在这种情况下不明确存在清理 所以我找到了一种方法,通过使用包装器函数(在这段代码中称为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
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)