1. 定义(如何理解装饰器):装饰器本生是闭包函数的一种应用,是指在不改变原函数的情况下为原函数添加新的功能的一个函数。它把被装饰的函数作为外层函数的参数传入装饰器,通过闭包操作后返回一个替代版函数。
  2. 遵循的原则: 开放封闭原则------在不改变调用方式和源代码的情况下,增加新功能。
    1. 不能改变被修饰对象(函数(后面还会对类进行装饰))的源代码(封闭)
    2. 不能改变被修饰对象(函数(以后还会对类进行装饰))的调用方式,且能达到增加功能的效果。(开放)
  3. 优点:
    1. 丰富了原函数的功能
    2. 提高了程序的可拓展性
  4. 装饰器的简单实现:
# 无参装饰器公式:
def fn():
print('原功能') def outer(fn):
def inner():
print('新功能1')
fn()
print('新功能2')
return inner
fn = outer(fn1)
print(fn())
"""
案例分析: 定义一个打印插花的函数,为其前面添加绘画功能,后面添加观赏功能。
如何一步一步完成完整的装饰器函数。
""" def vase():
print('插花') def wrap():
tag = vase # 此时的vase 是在wrap()还没有运行结束的时候,wrap没有返回值,所以tag被赋值的是vase原先的值。 def outer():
print('绘画')
tag() # 原先的vase
print('观赏') return outer # wrap()函数返回的是outer函数的地址空间 vase = wrap() # vase = outer vase()

上述代码,存在一个缺陷,就是没有写活,没办法将装饰器用在其他函数上,对于无参装饰器的正确的姿势应该如下:

def vase():
print('插花') def wrap(fn):
def outer():
print('绘画')
fn() # 原先的vase
print('观赏') return outer vase = wrap(vase) # vase = outer() vase()

那么如何让代码更简洁? python 提供一种语法糖,可以让代码看起来更简洁

def wrap(fn):
def outer():
print('绘画')
fn() # 原先的vase
print('观赏') return outer @wrap # 此语法糖形式,实际上就是完成了 vase = wrap(vase)操作 = outer
def vase():
print('插花') print(vase())

下面来看看如何进行多层装饰:(多层装饰注意一个顺序问题,执行时是从上向下执行,返回操作的时候是一层一层跳出)

def wrap1(fn):
def outer():
print('绘画')
fn() # 原先的vase
print('观赏') return outer def wrap2(fn):
def outer():
print('购买')
fn() # 原先的vase return outer @wrap2
@wrap1
def vase():
print('插花') vase() # 购买
# 绘画
# 插花
# 观赏 @wrap1
@wrap2
def vase():
print('插花') vase() # 绘画
# 购买
# 插花
# 观赏

5.有参有返的装饰器

def wrap(func):
def inner(*args, **kwargs): # 此处 *args (接收所有位置参数) 接收(a,b,c)以元组形式存储,kwargs (接收所有关键字参数) 则是接收{x:4,y:5,z:6}存成字典形式
print('新功能1')
res = func(*args, **kwargs)
print('新功能2')
return res return inner @wrap
def fn(a, b, c, *, x, y, z):
print(a, b, c, x, y, z) re = fn(1, 2, 3, x=4, y=5, z=6)
print(re) # 新功能1
# 1 2 3 4 5 6
# 新功能2
# None 返回值是None 因为函数fn本身无return

案例:在原登录功能下增加账号验证和密码验证功能

# 增加一个账号安全处理功能:3位英文字母或汉字
def check_pwd(fn):
def inner(usr, pwd):
if not (len(pwd) >= 6 and usr.isalpha()):
print('账号认证失败')
return False
return fn(usr, pwd) return inner # 增加一个密码处理功能 : 6位以上英文和数字组合 def check_usr(fn): # login = check_usr(login) = inner
def inner(usr, pwd):
if not (len(usr) >= 3 and usr.isalnum()):
print('密码认证失败')
return False
return fn(usr, pwd) return inner @check_usr # login = inner # 语法糖 谁现在下面谁先装功能,套在最外面(上面的)的是最先执行的
@check_pwd
# 登录功能
def login(usr, pwd):
if usr == 'qwe' and pwd == '':
print('登录成功')
return True
print('登录失败')
return False res1 = login('asdd', '')
res2 = login('as', '')
res3 = login('qwe', '')
res4 = login('qwe', '')
print(res1)
print(res2)
print(res3)
print(res4) # 账号认证失败
# 密码认证失败
# 账号认证失败
# 登录成功
# False
# False
# False
# True

带参装饰器(def wrap(参数们))

# 通过带参装饰器,实现增加颜色选择功能
def color_choice(color_inp):
def wrap(fn):
if color_inp == 'red':
info = 'red:new action'
else:
info = 'yellow:new action' def inner(*args, **kwargs):
res = fn(*args, **kwargs)
print(info)
return res return inner # wrap(fn) 返回的是 inner函数对象(地址) return wrap # color_choice 返回的是 wrap函数对象 color_choice(color_inp)() => wrap() => res color_inp = input('color:') @color_choice(color_inp)
def func():
print('func run ') func()

案例:查看个人主页前的登录状态验证

is_login = False

def login():
usr = input('usr:').lower()
if not (len(usr) >= 3 and usr.isalnum()):
print('密码认证失败')
return False
pwd = input('pwd:')
if usr == 'qwe' and pwd == '':
print('登录成功')
is_login = True
else:
print('登录失败')
is_login = False # 完成一个登录状态校验的装饰器
def check_login(fn):
def inner(*args, **kwargs):
if is_login != True:
print('你未登录')
login()
res = fn(*args, **kwargs)
return res
return inner # 查看个人主页功能
@check_login
def homepage():
print('个人主页') @check_login
# 销售功能
def sell():
print('销售页面') homepage()

day12--装饰器的更多相关文章

  1. day12:装饰器的进阶

    1,三元运算符:变量 = 条件返回True的结果 if 条件 else 条件返回false的结果:必须要有结果:必须要有if和else,只能是简单的情况. 2,传参包起来,星号打散 def outer ...

  2. day12 装饰器的模版

    1.什么是装饰器 装饰器指的是为被装饰对象(别人)添加新功能的工具 装饰器本身可以是任意可调用对象 被装饰器对象也可以是任意可调用对象 2.为何要用装饰器 开放封闭原则:指的是对修改封闭,对扩展开放 ...

  3. 总结day12 ----装饰器

    一,什么是装饰器? 装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象. 装饰器的应用场景:比如插入日志,性能测试,事 ...

  4. Day12装饰器

    1.装饰器 什么是装饰器:装饰器指的是为被装饰对象添加新功能的工具 装饰器本身可以是任意调用对象 被装饰对象本身也可以是任意可调用对象 2.为何要用装饰器: 开放封闭原则: ①对修改源代码和调用方式是 ...

  5. day11 - 15(装饰器、生成器、迭代器、内置函数、推导式)

    day11:装饰器(装饰器形成.装饰器作用.@语法糖.原则.固定模式) 装饰器形成:最简单的.有返回值的.有一个参数的.万能参数 函数起的作用:装饰器用于在已经完成的函数前后增加功能 语法糖:使代码变 ...

  6. Python——day12 nonlcoal关键字、装饰器(开放封闭原则、函数被装饰、最终写法)

    一.nonlocal关键字 1.作用:将L与E(E中的名字需要提前定义)的名字统一 2.应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值 def outer(): num=10 print ...

  7. DAY12、装饰器

    一.补充:nonlocal关键字 1.作用:将L与E(E中的名字需要提前定义)的名字统一 2.应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值 3.案例: def outer():    ...

  8. day12 十二、开放封闭、装饰器

    一.nonlocal关键词 # global # num = # def fn(): # global num # L>G 将局部的名字与全局统一 # num = # fn() # print( ...

  9. python 全栈开发,Day12(函数的有用信息,带参数的装饰器,多个装饰器装饰一个函数)

    函数的执行时,*打散.函数的定义时,*聚合. from functools import wraps def wrapper(f): # f = func1 @wraps(f) def inner(* ...

  10. 函数的有用信息,装饰器 day12

    一 函数的有用信息 本函数的功能:绘图功能,实时接收数据并绘图.:return: 绘图需要的数据,返回给前端某标签 def f1(): ''' 本函数的功能:绘图功能,实时接收数据并绘图. :retu ...

随机推荐

  1. python里文件读写操作

    文件读写操作一种基本操作,但是里面也存在很多需要注意的问题,例如字符编码.内存缓冲.指针位置等等.如果忽视这些问题就会引起很多不必要的麻烦.简单来说,文件的读写分为几个过程: 打开文件,并定义操作文件 ...

  2. Linux 安装 lrzsz,使用 rz、sz 上传下载文件

    yum install -y lrzsz 上传文件到服务器 rz 命令后会出现一个文件选择框,选择.确定即可 从服务器下载文件 sz 文件名即可

  3. ViewPager实现滑动翻页效果

    实现ViewPager的滑动翻页效果可以使用ViewPager的setPageTransformer方法,如下: import android.content.Context; import andr ...

  4. 初见jQuery EasyUI

    本文通过一个简单的小例子,简述jQuery EasyUI的使用方法,仅供学习分享使用,如有不足之处,还请指正. 什么是jQuery EasyUI ? 引用官网的一句话:jQuery EasyUI fr ...

  5. vue自定义一个v-model

    目标 js <template> <my-form v-model="form"> </my-form> </template> & ...

  6. 结对编程--四则运算(Java)萧英杰 夏浚杰

    结对编程--四则运算(Java)萧英杰 夏浚杰 Github项目地址 功能要求 题目:实现一个自动生成小学四则运算题目的命令行程序 使用 -n 参数控制生成题目的个数(实现) 使用 -r 参数控制题目 ...

  7. [20181206]关于一致性读取3.txt

    [20181206]关于一致性读取3.txt --//简单演示一致性读取以及如何读取undo重构数据块的.我不想转储对应的undo块,解析那些复杂的过程. 1.环境:SCOTT@book> @ ...

  8. mssql sqlserver 使用sql脚本检测数据表中一列数据是否连续的方法分享

    原文地址:http://www.maomao365.com/?p=7335 摘要:    数据表中,有一列是自动流水号,由于各种操作异常原因(或者插入失败),此列数据会变的不连续,下文将讲述使用sql ...

  9. Deep learning深度学习的十大开源框架

    Google开源了TensorFlow(GitHub),此举在深度学习领域影响巨大,因为Google在人工智能领域的研发成绩斐然,有着雄厚的人才储备,而且Google自己的Gmail和搜索引擎都在使用 ...

  10. java求解第N个素数(质数)

    面试中,遇到一个题目:求解第N个素数. import java.util.Scanner; public class GetPrimeNumber { public static int NthPri ...