使用 @contextmanager 装饰器的上下文管理器
装饰器是Python中非常强大和有用的工具,因为它允许程序员修改函数或类的行为。装饰器允许我们包装另一个函数以扩展被包装函数的行为,而无需永久修改它。
句法:
@decorator
def function(args):
statements(s)
例子:
Python3
# Python program to demonstrate
# decorators
def msg_decorator(func):
# Inner function
def msg_wrapper(msg):
print("A decorated line:", func(msg))
return msg_wrapper
# Using the decorator
@msg_decorator
def print_name(name):
return name
print_name("Pooventhiran")
Python3
# Python program to demonstrate
# Context Manager
with open('testfile.txt') as in_file:
print(''.join(in_file.readlines()))
Python3
# Python program creating a
# context manager
class ContextManager():
def __init__(self):
print('init method called')
def __enter__(self):
print('enter method called')
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
print('exit method called')
# Driver code
with ContextManager() as manager:
print('with statement block')
Python3
# Python program for creating a
# context manager using @contextmanager
# decorator
from contextlib import contextmanager
@contextmanager
def ContextManager():
# Before yield as the enter method
print("Enter method called")
yield
# After yield as the exit method
print("Exit method called")
with ContextManager() as manager:
print('with statement block')
A decorated line: Pooventhiran
在此示例中,每当调用 print_name() 时,首先会调用msg_decorator ,并将 print_name 作为参数。在 msg_decorator 内部,返回 msg_wrapper,它简单地调用传递给 msg_decorator 的任何函数,并使用传递给它的参数。虽然这个例子很简单,但这些在实际用例中非常强大,比如检查边界/特殊条件、预处理等。
注意:有关更多信息,请参阅Python中的装饰器。
上下文管理器
上下文管理器是 Python 的资源管理器。大多数情况下,我们使用文件作为资源(一种简单的资源)。我们通常不关心在执行结束时关闭文件。这是一种不好的编码习惯,当打开太多文件时,或者当程序因资源未正确释放而终止时,也会导致问题。上下文管理器通过自动管理资源来解决这个问题。在Python中,使用了 with 关键字。
例子:
Python3
# Python program to demonstrate
# Context Manager
with open('testfile.txt') as in_file:
print(''.join(in_file.readlines()))
在上面显示的示例中,使用的文件由 ContextManager 自己管理,因为即使程序失败,它也会关闭文件。这个上下文管理器功能也可以内置到我们的程序中。用户需要确保该类具有方法:__enter__() 和 __exit__()。让我们看一个带有这些特殊方法的模板。
Python3
# Python program creating a
# context manager
class ContextManager():
def __init__(self):
print('init method called')
def __enter__(self):
print('enter method called')
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
print('exit method called')
# Driver code
with ContextManager() as manager:
print('with statement block')
输出:
init method called
enter method called
with statement block
exit method called
在上面的代码中,__enter__ 将在控件进入时执行 with 和 __exit__,当控件离开时执行 with 子句。我们可以在 contextlib.contextmanager 装饰器的帮助下简单地将任何函数作为上下文管理器,而无需编写单独的类或__enter__和 __exit__ 函数。
使用@contextmanager
我们必须使用 contextlib.contextmanager 来装饰一个生成器函数,它只产生一次。 yield 之前的所有内容都被认为是 __enter__ 部分,之后的所有内容都是 __exit__ 部分。生成器函数应该产生资源。
例子:让我们用这个装饰器重写上面的例子
Python3
# Python program for creating a
# context manager using @contextmanager
# decorator
from contextlib import contextmanager
@contextmanager
def ContextManager():
# Before yield as the enter method
print("Enter method called")
yield
# After yield as the exit method
print("Exit method called")
with ContextManager() as manager:
print('with statement block')
输出:
Enter method called
with statement block
Exit method called