装饰器
装饰本质上就是一个闭包函数,它可以对我们已有函数进行额外的功能拓展,装饰器符合了 开发中的封闭开放原则
装饰器的作用
在不改变原有函数的源代码的情况下,给函数增加新的功能
def decorator(fn): # fn: 需要装饰的函数def inner():'''函数执行之前需要执行的代码'''fn() # 执行被装饰的目标函数'''函数执行之前需要执行的代码'''return inner
装饰器的使用
# 定义一个装饰器
def login(fn):def inner():print('登录')fn()return inner# 定义需要被装饰的函数
def comment():print('评论')comment = login(comment)
comment()
执行结果
装饰器语法糖
如果每次编写代码都要写comment = login(comment),那台麻烦了,所以就有了更简洁的写法,语法糖
格式:@装饰器名字
def login(fn):def inner():print('登录')fn()return inner@login
def comment():print('评论')comment()
执行结果
简单小案例
打印数字1-1000需要花费多少时间?
import timedef decorator(func):def inner():start_time = time.time()func()end_time = time.time()print(f"打印数字1-1000需要花费{end_time - start_time}")return inner@decorator
def func1():for i in range(1000):print(i)func1()
执行结果
装饰带有参数的函数
def decorator(fn):def inner(a, b):fn(a, b)return inner@decorator
def sum_num(a, b):result = a + bprint(result)sum_num(1, 2)
装饰的函数带有返回值
def decorator(fn):def inner(a, b):return fn(a, b)return inner@decorator
def sum_num(a, b):result = a + breturn resultresult = sum_num(1, 2)
print(result)
装饰的函数带有不定长参数
def decorator(fn):def inner(*args, **kwargs):fn(*args, **kwargs)return inner@decorator
def sum_num(*args, **kwargs):print(args, kwargs)sum_num(1, 2, 3, name='张三', age='李四')
通用装饰器
def decorator(fn):def inner(*args, **kwargs):result = fn(*args, **kwargs)return resultreturn inner@decorator
def sum_num(*args, **kwargs):return args, kwargsprint(sum_num(1, 2, 3, name='张三'))
多个装饰器的使用
多个装饰器装饰一个函数
def check1(fn):def inner():print('登录一')fn()return innerdef check2(fn):def inner():print('登录二')fn()return inner@check1
@check2
def comment():print('评论')comment()
执行结果
带有参数的装饰器
def check(flag): # 这里起到了函数里面的所有函数都能够用到flagdef decorator(fn):def inner(num1, num2):if flag == '+':print('正在进行加法运算')return fn(num1, num2)return innerreturn decorator@check('+') # 第一层函数只是为了接受参数
def add(a, b):result = a + breturn resultprint(add(1, 5))
执行结果
类装饰器
一个类里面一旦实现了__call__方法,那么这个类实例化出来的对象就可以像函数一样进行调用
class Check():num = 1def __call__(self):print('call方法被调用')print(self.num)result = Check()
result()
执行结果
使用类装饰器
class Check(object):def __init__(self, fn):self.__fn = fn # fn = commentdef __call__(self, *args, **kwargs):print('登录')self.__fn()@Check
def comment():print('评论')comment()
执行结果
property属性
property属性可以把类中的一个方法当作属性来进行使用
定义property属性有两种方式
- 装饰器方式
- 类属性方式
装饰器方式
@property 把方法当作属性使用,当获取属性时会执行下面修饰的方法
@方法名.setter 把方法当作属性使用,当设置属性时会执行下面修饰的方法
装饰器方法 的property属性修饰的方法名一定要一样
class Person(object):def __init__(self):self.__age = 18@propertydef age(self):return self.__age# 获取属性
p = Person()
print(p.age)
class Person(object):def __init__(self):self.__age = 18@propertydef age(self):return self.__age@age.setterdef age(self, new_age):self.__age = new_age# 获取属性
p = Person()
print(p.age)# 修改属性
p.age = 100
print(p.age)
类属性装饰器
property的参数说明:
第一个参数是获取属性时要执行的方法
第二个参数时设置属性时要执行的方法
class Person(object):def __init__(self):self.__age = 18def get_age(self):return self.__agedef set_age(self, new_age):self.__age = new_ageage = property(get_age, set_age)# 获取属性
p = Person()
print(p.age)# 修改属性
p.age = 100
print(p.age)