python 装饰器
装饰器
装饰本质上就是一个闭包函数,它可以对我们已有函数进行额外的功能拓展,装饰器符合了 开发中的封闭开放原则
装饰器的作用
在不改变原有函数的源代码的情况下,给函数增加新的功能
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 time
def 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 + b
print(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 + b
return result
result = 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 result
return inner
@decorator
def sum_num(*args, **kwargs):
return args, kwargs
print(sum_num(1, 2, 3, name='张三'))
多个装饰器的使用
多个装饰器装饰一个函数
def check1(fn):
def inner():
print('登录一')
fn()
return inner
def check2(fn):
def inner():
print('登录二')
fn()
return inner
@check1
@check2
def comment():
print('评论')
comment()
执行结果
带有参数的装饰器
def check(flag): # 这里起到了函数里面的所有函数都能够用到flag
def decorator(fn):
def inner(num1, num2):
if flag == '+':
print('正在进行加法运算')
return fn(num1, num2)
return inner
return decorator
@check('+') # 第一层函数只是为了接受参数
def add(a, b):
result = a + b
return result
print(add(1, 5))
执行结果
类装饰器
一个类里面一旦实现了__call__方法,那么这个类实例化出来的对象就可以像函数一样进行调用
class Check():
num = 1
def __call__(self):
print('call方法被调用')
print(self.num)
result = Check()
result()
执行结果
使用类装饰器
class Check(object):
def __init__(self, fn):
self.__fn = fn # fn = comment
def __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
@property
def age(self):
return self.__age
# 获取属性
p = Person()
print(p.age)
class Person(object):
def __init__(self):
self.__age = 18
@property
def age(self):
return self.__age
@age.setter
def 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 = 18
def get_age(self):
return self.__age
def set_age(self, new_age):
self.__age = new_age
age = property(get_age, set_age)
# 获取属性
p = Person()
print(p.age)
# 修改属性
p.age = 100
print(p.age)