一. 简介
本文来简单学习一下 Python3中的装饰器。
在 Python 3 中,装饰器(Decorator)是一种非常强大的工具,它允许你在不修改原有函数代码的情况下,动态地为函数添加额外的功能。
二. python3 中的装饰器
1. 装饰器的语法
Python 装饰器允许在不修改原有函数代码的基础上,动态地增加或修改函数的功能,装饰器本质上是一个接收函数作为输入并返回一个新的包装过后的函数的对象。装饰器的语法格式如下:
def decorator_function(original_function):def wrapper(*args, **kwargs):#这里是在调用原始函数前添加的新功能before_call_code()result = original_function(*args, **kwargs)#这里是在调用原始函数后添加的新功能after_call_code()return resultreturn wrapper#使用装饰器
@decorator_function
def targe_function(arg1, args2):pass #这里是原始函数的实现
语法解析如下:
decorator_function 是一个装饰器函数,它接受一个函数 func 作为参数,并返回一个内部函数 wrapper,在 wrapper 函数内部,你可以执行一些额外的操作,然后调用原始函数 func,并返回其结果。
(1) decorator_function是装饰器,它接收了一个 original_function() 函数 作为参数。
(2) wrapper 是内部函数,是 装饰器语法的一部分。它是实际会被调用的新函数,包裹了原始函数的调用,并在其前后增加了额外的行为。
(3) 当使用 @decorator_function前缀在 target_function定义函数定义前,表示target_function函数被装饰器decorator_function装饰。
python会自动将 target_function作为参数传递给 decorator_function装饰器函数,然后将返回的 wrapper 替换掉 target_function。
2. 示例
(1) 不带参数的装饰器
#!/usr/bin/env python3def my_decorator(func):def wrapper():print("Something is happening before the function is called")func()print("Something is happening after the function is called")return wrapper@my_decorator
def print_hello():print("hello")#调用被装饰的函数
print_hello()
输出如下:
Something is happening before the function is called
hello
Something is happening after the function is called
(2) 带参数的装饰器函数
#!/usr/bin/env python3def repeat(n):def my_my_decorator(func):def wrapper(*args, **kwargs):for index in range(n):result = func(*args, **kwargs)return resultreturn wrapperreturn my_my_decorator@repeat(5)
def greet(name):print(f"Hello, {name}!")#调用装饰器函数
greet("肖战")
输出:会输出 5遍 "Hello, 肖战!"
(3) 类装饰器
#!/usr/bin/env python3class count_class:def __init__(self, func):self.func = funcself.num_calls = 0def __call__(self, *args, **kwargs):self.num_calls += 1print(f"Call {self.num_calls} of {self.func.__name__}")return self.func(*args, **kwargs)@count_class
def print_msg():print("Hello!")#调用被装饰的函数
print_msg()
print_msg()
以上示例中:
count_class
是一个类装饰器,它接受函数func
作为参数,并在每次调用func
时记录调用次数。__call__
方法使类实例可以像函数一样被调用,因此, print_msg 实际上调用的是 count_class实例的__call__
方法。
三. 装饰器的应用
通过使用装饰器,你可以实现诸如日志记录、性能测量、访问控制等功能,而无需直接修改函数的内部逻辑。装饰器的应用场景:
日志记录: 装饰器可用于记录函数的调用信息、参数和返回值。
性能分析: 可以使用装饰器来测量函数的执行时间。
权限控制: 装饰器可用于限制对某些函数的访问权限。
缓存: 装饰器可用于实现函数结果的缓存,以提高性能。
装饰器的核心思想是“包装”一个函数,以便在调用该函数时执行一些额外的操作。装饰器可以用来修改函数的行为,但不会改变函数的原始定义。