📜  说明Python中装饰器的有用案例

📅  最后修改于: 2022-05-13 01:54:19.994000             🧑  作者: Mango

说明Python中装饰器的有用案例

装饰器是一种特殊的函数,它要么接受一个函数并返回一个函数,要么接受一个类并返回一个类。好吧,它可以是任何可调用的(即可以调用的函数、类、方法),它可以返回任何内容,也可以采用方法。这也称为元编程,因为程序的一部分试图在编译时修改程序的另一部分。
让我们深入研究Python装饰器并找出它们可以做什么。这不会涵盖基础知识或带有参数的装饰器,而是一些有用的示例来说明这种情况。

基本上,装饰器接受一个可调用对象,任何实现特殊方法__call()__的对象都被称为可调用对象,添加一些功能并返回一个可调用对象。

示例 1:

# Python program to demonstrate
# decorators
  
  
# Creating a decorator
def decorated_func(func):
    def inner():
        print("This is decorated function")
        func()
    return inner()
  
  
def ordinary_func ():
    print("This is ordinary function")
  
decorated = decorated_func(ordinary_func)
decorated

输出:

This is decorated function
This is ordinary function

在上面显示的示例中, decorated_func()是一个装饰器。简而言之,装饰器充当包装对象(不改变原始对象)并向原始对象添加新功能的包装器。这是一个常见的结构,所以Python有一个语法特性(称为Decorator )来简化它。例如,

这:

@decorated_func
def ordinary_func():
     print("This is ordinary function")

相当于:

def ordinary_func():
    print("This is ordinary function")
decorated = decorated_func(ordinary_func)

一个简单的例子是:

示例 2:
输入:

def mul_decorator(func):
    def wrapper(*args, **kwargs):
        print('function', func.__name__, 'called with args - ', /
              args, 'and kwargs - ', kwargs)
        result = func(*args, **kwargs)
        print('function', func.__name__, 'returns', result)
        return result
    return wrapper
  
  
@mul_decorator
def mul(a, b):
    return a * b
mul(3, 3)
mul(3, b = 6)

输出:

function mul called with args -  (3, 3) and kwargs -  {}
function mul returns 9
function mul called with args -  (3,) and kwargs -  {'b': 6}
function mul returns 18

您还可以将内置插件用作装饰器

示例 3:

# func will be func = type(func) -> 
@type
def func(): 
    return 42
  
print(func)
  
# print doesn't return anything, so func == None
@print
def func2(): 
    return 42
  
# Prints None
print(func2)

输出:



None

您可以用其他东西替换装饰对象

示例 4:

# Creating a decorator
class function_1:
    def __init__(self, func):
        self.func = func
        self.stats = []
  
    def __call__(self, *args, **kwargs):
        try:
            result = self.func(*args, **kwargs)
        except Exception as e:
            self.stats.append((args, kwargs, e))
            raise e
        else:
            self.stats.append((args, kwargs, result))
            return result
  
    @classmethod
    def function_2(cls, func):
        return cls(func)
  
  
@function_1.function_2
def func(x, y):
    return x / y
  
print(func(6, 2))
  
print(func(x = 6, y = 4))
  
func(5, 0)
print(func.stats)
print(func)

输出:

3.0
1.5
Traceback (most recent call last):
  File "/home/1ba974e44c61e303979b3ee120b6b066.py", line 29, in 
    func(5, 0)
  File "/home/1ba974e44c61e303979b3ee120b6b066.py", line 11, in __call__
    raise e
  File "/home/1ba974e44c61e303979b3ee120b6b066.py", line 8, in __call__
    result = self.func(*args, **kwargs)
  File "/home/1ba974e44c61e303979b3ee120b6b066.py", line 23, in func
    return x / y
ZeroDivisionError: division by zero

请注意原来的"func"是如何被"function_1"的一个实例替换的,它的使用方式与原来的函数相同。
您可以与系统中的其他对象创建关系

示例 5:

def dict_from_func(func):
    return {func.__name__: func}
  
  
activity = {}
  
@activity.update
@dict_from_func
def mul(a, b):
    return a * b
  
  
@activity.update
@dict_from_func
def add(a, b):
    return a + b
  
  
print(mul)
print(activity)
print(activity['mul'](2, 5))

输出:

None
{'mul': , 
 'add': }
10

在这里,在示例 5 中,我们使用了dict.update方法作为装饰器,即使它不是为此而设计的。这是可能的,因为dict_from_func返回一个字典,而dict.update将一个字典作为参数。

实际上,这个:

@activity.update
@dict_from_func
def mul(a, b):
    return a * b

等于——

def mul(a, b):
    return a * b
mul = activity.update(dict_from_func(mul))

结论

装饰器是一个有趣且令人惊叹的功能,可用于多种用途。它不仅仅是“接受函数或类并返回函数或类的函数或类”