1.装饰器
1.1作用:在函数名以及函数体不改变的前提下,给一个函数附加一些额外代码。
1.2语法:
1.3案例:
发说说,发图片
“开放封闭”原则:已经写好的代码,尽可能的不要修改。如果想要新增功能,在原先代码的基础上,单独进行扩展。
“单一职责”原则:
# 定义两个功能函数 # def fss(): # print("发说说") # # def ftp(): # print("发图片") # 写一些相关的逻辑代码 # btnIndex = 1 # if btnIndex == 1: # fss() # else: # ftp() # 发说说与发图片必须有一个前提,就是,用户必须登录之后才能操作。 # 身份登录验证的操作。 # 第一种方式,直接在业务逻辑代码里面去修改,添加一个验证操作。 # 这是一种最不好的方式,因为业务逻辑代码非常多,所以,就造成了,每一份,逻辑代码,在代用具体的功能函数之前,都需要去做登 # 录验证。代码冗余度就比较大。代码的复用性比较差。代码的维护性比较差。 # btnIndex = 1 # if btnIndex == 1: # print("登录验证......") # fss() # else: # print("登录验证......") # ftp() # 第二种方式,直接在功能函数中做修改。方便代码的重用。 # def fss(): # print("登录验证......") # print("发说说") # # def ftp(): # print("登录验证......") # print("发图片") # # # btnIndex = 2 # if btnIndex == 1: # fss() # else: # ftp() # 第三种方式:独立写一个登录验证的功能函数。 # def checkLogin(): # print("登录验证......") # # def fss(): # checkLogin() # print("发说说") # # def ftp(): # checkLogin() # print("发图片") # # # btnIndex = 2 # if btnIndex == 1: # fss() # else: # ftp() # 第四种方式:用装饰器,给原来的函数增加一个新的功能,而不改变原函数。 # 语法糖:@checkLogin def checkLogin(func): def inner(): print("登录验证......") func() return inner # 语法糖:@checkLogin @checkLogin # 等同于fss = checkLogin(fss) def fss(): print("发说说") # fss = checkLogin(fss) # fss = def inner(): # print("登录验证......") # fss() # print(fss) # 语法糖:@checkLogin @checkLogin # 等同于ftp = checkLogin(ftp) def ftp(): print("发图片") # ftp = checkLogin(ftp) # 要保证这边的业务逻辑代码不改变 btnIndex = 2 if btnIndex == 1: fss() # checkLogin(fss) else: ftp() # checkLogin(ftp)
1.4注意:装饰器的执行时间,是立即执行
# 给fss函数增加一些额外的功能: # 1.函数名字不能发生改变 # 2.函数体内部代码不能发生改变 def check(func): print("xxxxxx") def inner(): #这一部分是个闭包 print("登录验证操作") # func() # return inner @check def fss(): print("发说说") # fss()
1.5进阶:
装饰器叠加:从上到下叠加,从下到上执行。
def line(func): def inner(): print("----------------------------------------") func() return inner def line2(func): def inner(): print("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") func() return inner @line # 等同于 print_content = line(print_content) @line2 # 等同于 print_content = line2(print_content) # print("----------------------------------------") 这是装饰器叠加的运行流程 # print("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") # print("社会我佳爷,人狠话不多!") def print_content(): print("社会我佳爷,人狠话不多!") print_content()
对有参函数进行装饰:
def zsq(func): def inner(*args, **kwargs): print("-" * 30) func(*args, **kwargs) return inner @zsq def pnum(num, num2): print(num, num2) @zsq def pnum2(num): print(num) pnum(100, 1000) pnum2(1000000000) @zsq def pnum3(num): print(num) pnum3(num=666)
对有返回值的函数进行装饰:无论什么场景,保持函数返回值一致。
def zsq(func): def inner(*args, **kwargs): print("-" * 30) res = func(*args, **kwargs) return res return inner @zsq def pnum(num, num2, num3): print(num, num2, num3) return num + num2 + num3 @zsq def pnum2(num): print(num) res1 = pnum(1, 2, 3) res2 = pnum2(888888) print(res1, res2)
带有参数的装饰器:通过@装饰器(参数)的方式,调用这个函数,并传递参数,并把返回值,再次当做装饰器使用。先计算@后面的内容,把这个内容当做是装饰器。
#要求装饰器在打印666之前打印一行---- # def line(func): # def inner(): # print("-" * 30) # func() # return inner # # def line1(func): # def inner(): # print("=" * 30) # func() # return inner # # def line2(func): # def inner(): # print("*" * 30) # func() # return inner # 以上的三种情况可以将一直在变的符号,换成一个变量,只需修改变量就能达到不同的效果 def getzsq(char): def zsq(func): def inner(): print(char * 30) func() return inner return zsq @getzsq("=") def f1(): print("666") f1()