基于类的上下文管理器与基于生成器的上下文管理器

时间:2018-12-04 10:41:31

标签: python

有一个Indenter()类,我们可以使用这样的文本缩进级别:

    hi!
        hello
            bonjour

上下文管理器基于类的实现是:

class Indenter:
    def __init__(self):
        self.level = 0

    def __enter__(self):
        self.level += 1
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.level -= 1

    def print(self, text):
        print('    ' * self.level + text)


with Indenter() as indent:
    indent.print('hi')
    with indent:
        indent.print('hello!')
        with indent:
            indent.print('bonjour')

我想知道是否可以在基于生成器的上下文管理器中实现相同的解决方案?我尝试的解决方案没有用,可能是因为我不了解上下文管理器的想法...

更新: 这是我使用板载打印功能的方法,因此上下文会产生此功能。更好,但仍然仅适用于单个缩进:

from contextlib import contextmanager

@contextmanager
def indenter():
    level = 0
    def prints(text):
        print('____' * level + text)
    try:
        level += 1
        yield prints
    finally:
        level -= 1

with indenter() as ind:
    ind('aaaa')
    with ind:
        ind('bbbbb')

____aaaa
---------------------------------------------------------------------------
AttributeError     Traceback (most recent call last)
     29 with indenter() as ind:
     30     ind('aaaa')
---> 31     with ind:
     32         ind('bbbbb')

AttributeError: __enter__

2 个答案:

答案 0 :(得分:1)

我想到了这个。可以按与您的类版本类似的方式使用它(但不完全相同)。

from contextlib import contextmanager

def indenter():
    level = 0

    def prints(text):
        print('____' * level + text)

    @contextmanager
    def ind():
        nonlocal level
        try:
            level += 1
            yield prints
        finally:
            level -= 1
    return ind


ind = indenter()
with ind() as prints:
    prints('aaa')
    with ind() as prints:
        prints('bbb')
        with ind() as prints:
            prints('ccc')

输出:

____aaa
________bbb
____________ccc

答案 1 :(得分:0)

好的,这对我有用:

from contextlib import contextmanager

@contextmanager
def indenter(level=0):
    def prints(text):
        print('____' * level + text)
    try:
        level += 1
        yield prints
    finally:
        level -= 1


with indenter() as ind:
    print('0000')
    ind('1111')
    with indenter(1) as ind:
        ind('2222')

输出:

0000
____1111
________2222