Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.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_Python Decorators_Contextmanager - Fatal编程技术网

Python中上下文管理器和装饰器的区别

Python中上下文管理器和装饰器的区别,python,python-decorators,contextmanager,Python,Python Decorators,Contextmanager,两者的主要区别是什么?我一直在学习Python,并遇到了它们。装饰器本质上是一个包装另一个函数的函数,您可以在特定函数执行之前和之后执行任何操作 def my_decorator(some_function): def wrapper(*args, **kwargs): print("Do something before the function is called") some_function(*args, **kwargs) pri

两者的主要区别是什么?我一直在学习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')
收益率之前的所有内容都被视为“进入”的一部分,而收益率之后的所有内容都被视为“退出”的一部分


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

它们是完全不同的概念

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

修饰符是对函数或类定义的修改。它运行的代码在定义函数时替换该函数

@D
def Y(...):
    ...
这只是另一种写作方式

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

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

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

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

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