一、装饰器的分类:通用装饰器;类装饰器;property属性装饰器
- 装饰器的作用:在不改变原有函数源代码的情况下,给函数增加新的功能。(装饰器其实也是闭包的一种)
-
语法格式:
装饰器 def decorator(fn): # fn为被装饰的目标函数 def inner(): '''执行函数之前''' fn() # 执行装饰的目标函数 '''执行函数之后''' return inner
- 使用步骤:
# 定义一个装饰器
def check(fn):
def inner():
print("请先登录-----")
fn()
return inner
# 定义一个被装饰的函数
# 方法一:
@check
def comment():
print("发表评论")
# 使用装饰器装饰函数
# 方法二:comment = check(comment)
# 调用函数
comment()
注意:① fn = comment => fn() = comment()
②check的返回值为inner ,=> comment = inner => comment() = inner。【这里的comment函数发生了改变】
3、使用@符号也能执行刚才的方法, @check 与 comment = check(comment)的效果相同。
二、通用装饰器的使用:
- 装饰带有参数的函数
示例:
# 定义装饰器
def loggin(fn): # fn = sum_num
def inner(a,b):
fn(a,b)
return inner # sum_num = inner
# 使用装饰器装饰函数
@loggin
def sum_num(a,b):
result = a + b
print(result)
# 调用函数
sum_num(1,2)
2.装饰带有返回值的函数:
# 定义装饰器
def loggin(fn): # fn = sum_num
def inner(a,b):
result = fn(a,b)
return result
return inner # sum_num = inner
# 使用装饰器装饰函数
@loggin
def sum_num(a,b):
result = a + b
return result
# 调用函数
result = sum_num(1,2)
print(result)
3.装饰带有不定参数的函数:
# 定义装饰器
def loggin(fn): # fn = sum_num
def inner(*args, **args):
fn(*args, **args)
return inner # sum_num = inner
# 使用装饰器装饰函数
@loggin
def sum_num(*args, **kwargs):
print(args,kwargs)
# 调用函数
sum_num(1,2,age = "18")
4.多个装饰器的使用:
# 定义装饰器1
def check1(fn1):
def inner1():
print("登录验证1")
fn1()
return inner1
# 定义装饰器2
def check2(fn2):
def inner2():
print("登录验证2")
fn2()
return inner2
# 被装饰的函数
@check1
@check2
# 离函数近的装饰器先装饰,然后外面的装饰器再进行装饰,由内到外的过程
def comment():
print("发表评论")
# 调用函数
comment()
5.带参数的装饰器:
# 装饰器
def loggin(flag): # flag = "+"
# 外部函数
def decorator(fn):
# 内部函数
def inner(num1,num2):
# 判断过程
if flag == "+":
print("--正在努力进行加法计算--")
elif flag == "-":
print("--正在努力进行减法运算--")
result = fn(num1,num2)
return result
return inner
# 返回装饰器
return decorator
# 被带有参数装饰器装饰的函数
@decorator("+") # 1.loggin("+") 2.@decorator起到装饰器的功能了
def add(a,b):
result = a + b
return result
# 执行函数
result = add(1, 3)
print(result)
注:①装饰器的外部函数只接受一个参数---被装饰的函数
②需要给装饰器传参数需要在装饰器的外部再增加一个函数
三、类装饰器
1.__call__方法的使用:
一个类里面一旦实现了__call__方法,那么这个类创建的对象就是一个可调用的对象,可以像函数一样进行调用。
2.示例:
# 定义类装饰器
class Check(object):
def __init__(self,fn):
self.__fn = fn
def __call__(self, *args, **kwargs):
print("登录")
self.__fn() # comment()
# 被装饰的函数
@Check # comment = Check(comment)
def comment():
print("发表评论")
# 调用函数
comment()
注:①想要让类的实例对象能够像函数一样进行调用,需要在类里面使用call方法,把类的实例变成可调用对象。
②类装饰器装饰功能在call方法里面添加。
四、property属性装饰器
1、定义:property属性就是负责把类中的一个方法当做属性进行使用,这样可以简化代码。
2、定义property属性有两种方式:①装饰器方式;②类属性方式。
3、装饰器方式:
示例:
class Person(object):
def __init__(self):
self.__age = 0
# 装饰器方式的property,把age方法当做属性使用,表示当获取属性时会执行下面修饰的方法
@property
def age(self):
return self.__age
# 把age方法当做属性使用,表示当获取属性时会执行下面修饰的方法
@age.setter
def age(self,new_age):
if new_age >= 150:
print("成精了")
else:
self.__age = new_age
# 调用函数
p = Person()
# 得到函数值
p.age
print(p.age)
# 设置修改函数值
p.age = 88
print(p.age)
注:•@property 表示把方法当做属性使用,表示获取属性时会执行下面修饰的方法。
•@方法名.setter 表示把方法当做属性使用,表示当设置属性时会执行下面修饰的方法。
•装饰器方式的property属性1修饰的方法名一定要一样.
4.类属性方式:
示例
class Person(object):
def __init__(self):
self.__age = 0
def get_age(self):
'''当获取get属性的时候会执行该方法'''
return self.__age
def set_age(self,new_age):
'''当设置age属性的时候会执行该方法'''
if new_age >= 150:
print("成精了")
else:
self.__age = new_age
# 类属性的方式property属性
age = property(get_age,set_age)
p = Person)
print(p.gae)
print(p.age = 88)