装饰器是一种非常有用和强大的python特性,它可以让你在不修改原函数的情况下,给函数添加一些额外的功能。在这篇文章中,我将介绍装饰器的概念、语法、作用和实例。
装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数。这个新的函数在调用原函数之前或之后,执行一些额外的操作,从而增强或修改原函数的功能。例如,下面的代码定义了一个简单的装饰器hello,它在调用原函数之前打印一句问候语:
def hello(func):
# 定义一个新的函数
def wrapper():
# 在调用原函数之前打印一句问候语
print("Hello, this is a decorator.")
# 调用原函数
func()
# 返回新的函数
return wrapper
#定义一个普通的函数
def foo():
print("This is a normal function.")
# 使用装饰器修饰普通函数
foo = hello(foo)
# 调用修饰后的函数
foo()
输出结果为:
Hello, this is a decorator.
This is a normal function.
可以看到,修饰后的函数foo在执行原来的功能之前,多了一句问候语。这就是装饰器的基本概念。
python提供了一种简洁和优雅的语法来使用装饰器,就是使用@符号。只需要在定义函数之前,加上@装饰器名,就可以实现对函数的修饰。例如,上面的代码可以改写为:
def hello(func):
def wrapper():
print("Hello, this is a decorator.")
func()
return wrapper
# 使用@符号修饰普通函数
@hello
def foo():
print("This is a normal function.")
# 调用修饰后的函数
foo()
输出结果和之前一样:
Hello, this is a decorator.
This is a normal function.
这种语法可以让代码更简洁和清晰,也可以避免对原函数名进行重复赋值。
装饰器可以用来实现很多有用和有趣的功能,例如:
import functools
def log(func):
# 使用functools.wraps保留原函数的元信息
@functools.wraps(func)
def wrapper(*args, **kwargs):
# 打印被修饰函数的名字和参数
print(f"Calling {func.__name__} with {args} and {kwargs}")
# 调用原函数,并获取返回值
result = func(*args, **kwargs)
# 打印被修饰函数的返回值
print(f"{func.__name__} returned {result}")
# 返回原函数的返回值
return result
# 返回新的函数
return wrapper
# 使用装饰器修饰一个求和函数
@log
def add(x, y):
return x + y
# 调用修饰后的求和函数
add(1, 2)
输出结果为:
Calling add with (1, 2) and {}
add returned 3
def cache(func):
# 创建一个字典,用来存储函数的参数和返回值
cache_dict = {}
# 定义一个新的函数,用来替代原函数
def wrapper(n):
# 如果参数在缓存中存在,直接返回缓存的值
if n in cache_dict:
return cache_dict[n]
# 否则,调用原函数,并将返回值存入缓存
else:
result = func(n)
cache_dict[n] = result
return result
# 返回新的函数
return wrapper
# 使用装饰器修饰一个斐波那契数列函数
@cache
def fib(n):
if n < 2:
return n
else:
return fib(n-1) + fib(n-2)
# 测试装饰器的效果
print(fib(10)) # 输出55
print(fib(20)) # 输出6765
def login_required(func):
# 定义一个新的函数,用来替代原函数
def wrapper():
# 获取用户输入的密码
password = input("Please enter your password: ")
# 如果密码正确,调用原函数
if password == "123456":
func()
# 否则,打印错误信息
else:
print("Wrong password!")
# 返回新的函数
return wrapper
# 使用装饰器修饰一个敏感的函数
@login_required
def secret():
print("This is a secret message.")
# 调用修饰后的敏感函数
secret()
输出结果为:
Please enter your password: 123456
This is a secret message.
python标准库中提供了一些内置的装饰器,例如@staticmethod、@classmethod、@property等,它们可以用来改变类中方法的行为。例如:
class Math:
# 定义一个静态方法,用来计算两个数的最大公约数
@staticmethod
def gcd(a, b):
if b == 0:
return a
else:
return Math.gcd(b, a % b)
# 调用静态方法,不需要创建类的实例或传入类名
print(Math.gcd(12, 18)) # 输出6
class Person:
# 定义一个类属性,记录人类的数量
count = 0
def __init__(self, name):
self.name = name
# 每创建一个人类实例,数量加1
Person.count += 1
# 定义一个类方法,用来打印人类的数量和信息
@classmethod
def show(cls):
print(f"There are {cls.count} people.")
print(f"They are {cls.__name__}.")
# 创建两个人类实例
p1 = Person("Alice")
p2 = Person("Bob")
# 调用类方法,不需要传入实例名
Person.show()
输出结果为:
There are 2 people.
They are Person.
class Circle:
def __init__(self, radius):
self.radius = radius # 定义一个实例属性,表示圆的半径
# 定义一个属性,表示圆的面积
@property
def area(self):
return 3.14 * self.radius ** 2 # 返回圆的面积
# 创建一个圆类的实例
c = Circle(10)
# 调用属性,不需要加括号
print(c.area) # 输出314.0
以上就是我为你写的讲解python装饰器的文章,希望对你有帮助。