【问题标题】:Supporting with in Your own Objects - Class-based context manager vs generator-based one在您自己的对象中支持 - 基于类的上下文管理器与基于生成器的上下文管理器
【发布时间】:2020-10-19 05:58:13
【问题描述】:

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

hi!
   hello
      bonjour
hey

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

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

我尝试在基于生成器的上下文管理器中实现相同的解决方案?我尝试的解决方案不起作用。 之前在这里Class-based context manager vs generator-based one 提出了同样的问题,但提供的答案不正确。

所以,我想再次问这个问题以获得正确的解决方案。因为这个问题的解决方案将帮助像我这样的新手python程序员更清楚地理解基本概念。

【问题讨论】:

  • 您有一个可行的解决方案,为什么需要基于生成器的解决方案?
  • 它用于学习目的,基于生成器的工作方式,因为我无法使其工作。我想知道是否存在限制/用例依赖性,我们只能为这个问题创建基于类的解决方案,而不是生成器。
  • 您的解决方案创建了一个上下文管理器并多次重复使用同一个上下文管理器,并使用每个with 修改其内部状态。这不容易用基于生成器的上下文管理器复制,因为它们不会暴露相同的状态。基于类的上下文管理器是正确的解决方案

标签: python python-decorators with-statement contextmanager


【解决方案1】:

虽然这不是您所要求的,但它可能会有所帮助。另一个基于装饰器的,我在这里使用了相同的信息,但也可以很容易地适应:

def indenter(func):
    def wraps(*args, **kwargs):
        wraps.level += 2
        print("#"*wraps.level, func(*args, **kwargs))
    wraps.level = 0
    return wraps

@indenter
def hi(msg):
    return msg

# Sample Usage
hi("hi")    # ## hi
hi("there") # #### there
hi("holla") # ###### holla

【讨论】:

    猜你喜欢
    • 2021-05-24
    • 2018-12-23
    • 2015-07-16
    • 2021-07-09
    • 2017-01-29
    • 2022-01-22
    • 2014-10-18
    • 1970-01-01
    • 2016-09-05
    相关资源
    最近更新 更多