【问题标题】:Difference between Context Managers and Decorators in PythonPython中上下文管理器和装饰器之间的区别
【发布时间】:2018-11-22 05:22:00
【问题描述】:

两者的主要区别是什么?我一直在研究 Python 并遇到了它们。装饰器本质上是一个包装另一个函数的函数,您可以在特定函数执行之前和之后执行任何操作。

def my_decorator(some_function):
    def wrapper(*args, **kwargs):
        print("Do something before the function is called")
        some_function(*args, **kwargs)
        print("Do something after the function is called")

    return wrapper

@my_decorator
def addition(a, b):
    result = a+b
    print("Addition of {} and {} is {}".format(a,b,result))

但是在学习了 Context Manager 之后,我忍不住注意到它也有一个 enterexit ,您可以在其中执行大多数类似的操作。

from contextlib import contextmanager

@contextmanager
def open_file(path, mode):
    the_file = open(path, mode)
    yield the_file
    the_file.close()

files = []

for x in range(100000):
    with open_file('foo.txt', 'w') as infile:
        files.append(infile)

for f in files:
    if not f.closed:
        print('not closed')

yield 之前的所有内容都作为“进入”的一部分,而在“退出”之后的所有内容。

尽管上下文管理器和装饰器在语法上有所不同,但它们的行为可以被视为相似。那么区别是什么呢?应该使用其中任何一个的不同场景是什么?

【问题讨论】:

    标签: python python-decorators contextmanager


    【解决方案1】:

    它们是完全不同的概念,不应从同一角度看待。

    装饰器允许您在定义函数或类时增加或替换它。这比仅仅在函数调用之前或之后执行的事情要广泛得多。当然,你的特定装饰器可以让你在函数调用之前和之后做一些事情,只要没有引发异常,或者你明确地处理异常。但是您也可以使用装饰器向函数对象添加属性,或更新某种注册表。或者返回完全不同的东西并忽略原始函数。或者生成一个包装器来操作传入的参数或原始函数的返回值。上下文管理器不能做任何这些事情。

    另一方面,上下文管理器可以让您抽象出try: ... finally: constructs,因为无论块如何退出,您都可以在块的末尾执行更多代码。即使该块引发异常,或使用return 退出函数,上下文管理器__exit__ 方法仍将被调用,不管。上下文管理器甚至可以抑制块中引发的任何异常。

    这两个概念在其他方面根本不相关。当您需要对定义的函数或类进行某些操作时,请使用装饰器。如果您想在块结束后进行清理或执行其他操作,请使用上下文管理器。

    【讨论】:

      【解决方案2】:

      它们是完全不同的概念。

      上下文管理器是与 python with 关键字一起使用的对象。它在进入区块和退出区块时运行代码。

      装饰器是对函数或类定义的修改。它运行的代码会替换正在定义的函数。

      @D
      def Y(...):
          ...
      

      只是另一种写作方式

      def Y(...):
          ....
      Y = D(Y)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-01
        • 2012-03-02
        • 1970-01-01
        • 2015-12-12
        • 1970-01-01
        • 2021-08-24
        • 2012-01-09
        • 2016-03-16
        相关资源
        最近更新 更多