1、装饰器简介
Python 的装饰器是一种非常有用的功能,可以使用户在不修改原有函数或方法定义的情况下,给这些函数或方法增加额外的功能。装饰器本质上是一个函数,它接受一个函数作为参数并返回一个新的函数。装饰器可以使代码更简洁。
import time
def log_calls(func):
def wrapper(*args,**kwargs):
now = time.time()
print("Calling {0} with {1} and {2}".format(func.__name__,args,kwargs))
return_value = func(*args, **kwargs)
print("Executed {0} in {1}ms".format(func.__name__,time.time()-now))
return return_value
return wrapper
def test1(a,b,c):
print("test1 called")
def test2(a,b):
print("test2 called")
def test3(a,b):
print("test3 called")
time.sleep(1)
test1 = log_calls(test1)
test2 = log_calls(test2)
test3 = log_calls(test3)
>>> test1(1,2,3)
Calling test1 with (1, 2, 3) and {}
test1 called
Executed test1 in 0.00017595291137695312ms
>>> test2(4,b=5)
Calling test2 with (4,) and {'b': 5}
test2 called
Executed test2 in 9.918212890625e-05ms
>>> test3(6,7)
Calling test3 with (6, 7) and {}
test3 called
Executed test3 in 1.0013248920440674ms
通过装饰器实现上述代码,
import time
def log_calls(func):
def wrapper(*args,**kwargs):
now = time.time()
print("Calling {0} with {1} and {2}".format(func.__name__,args,kwargs))
return_value = func(*args, **kwargs)
print("Executed {0} in {1}ms".format(func.__name__,time.time()-now))
return return_value
return wrapper
@log_calls
def test1(a,b,c):
print("test1 called")
@log_calls
def test2(a,b):
print("test2 called")
@log_calls
def test3(a,b):
print("test3 called")
time.sleep(1)
>>> test1(1,2,3)
Calling test1 with (1, 2, 3) and {}
test1 called
Executed test1 in 0.00017595291137695312ms
>>> test2(4,b=5)
Calling test2 with (4,) and {'b': 5}
test2 called
Executed test2 in 9.918212890625e-05ms
>>> test3(6,7)
Calling test3 with (6, 7) and {}
test3 called
Executed test3 in 1.0013248920440674ms
@log_calls这样的写法就是使用装饰器
2、通过装饰器创建property
使用@property
可以创建出既简洁又易于使用的类接口,同时还能保持对数据的严格控制。通过使用property
装饰器,可以创建出既安全又易于使用的类接口,同时还能保持代码的简洁性和灵活性。
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
"""获取圆的半径"""
return self._radius
@radius.setter
def radius(self, value):
"""设置圆的半径,并进行简单的校验"""
if value < 0:
raise ValueError("Radius cannot be negative")
self._radius = value
@property
def diameter(self):
"""计算并返回圆的直径"""
return self._radius * 2
# 使用Circle类
circle = Circle(5)
print(circle.radius) # 获取半径,输出: 5
print(circle.diameter) # 获取直径,输出: 10
circle.radius = 10 # 设置半径
print(circle.radius) # 再次获取半径,输出: 10
print(circle.diameter) # 再次获取直径,输出: 20
# 尝试设置半径为负数,将抛出ValueError
# circle.radius = -2