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. HTML5 常用标签整理

    <!--1.  html5 文本 --> <div> <header> <hgroup> <h1>h1</h1> <h2& ...

  2. cf1136D. Nastya Is Buying Lunch(贪心)

    题意 题目链接 给出一个排列,以及\(m\)个形如\((x, y)\)的限制,表示若\(x\)在\(y\)之前则可以交换\(x, y\). 问\(n\)位置上的数最多能前进几步 \(n \leqsla ...

  3. Python相关机器学习‘武器库’

    开始学习Python,之后渐渐成为我学习工作中的第一辅助脚本语言,虽然开发语言是Java,但平时的很多文本数据处理任务都交给了Python.这些年来,接触和使用了很多Python工具包,特别是在文本处 ...

  4. Asp.Net MVC 利用ReflectedActionDescriptor判断Action返回类型

    System.Web.Mvc.ReflectedActionDescriptor descriptor = filterContext.ActionDescriptor as System.Web.M ...

  5. 【linux】Can't connect to local MySQL server through socket和Plugin 'auth_socket' is not loaded报错

    真的是一次吐血的经历,弄了两个多小时才弄好. 问题1:直接登陆root用户报错 ERROR 2002 (HY000): Can't connect to local MySQL server thro ...

  6. git 代码服务器的网页版gitweb的搭建

    sudo apt-get install apache2 git-core gitwebsudo a2enmod rewrite #vi /etc/gitweb.conf $projectroot = ...

  7. AS插件-GsonFormat

    支持 field 类型的修改. 支持快捷键打开 GsonFormat ,默认为 option+s(mac), alt+s(win) 支持 field 名称的修改. 支持添加 field 前缀. 支持多 ...

  8. DAY14(PYTHONS)生成器进阶

    def average(): sum = 0 count = 0 avg = 0 while True: #循环 num = yield avg #遇到yield就停止,防止一开始除数为0导致崩溃 s ...

  9. git 入门教程之变基合并

    git 鼓励大量使用分支---"早建分支!多用分支!",这是因为即便创建再多的分支也不会造成存储或内存开销,并且分支的作用有助于我们分解逻辑工作,这样一样其实比维护单一臃肿分支要简 ...

  10. Spark DataFrame的groupBy vs groupByKey

    在使用Spark SQL的过程中,经常会用到groupBy这个函数进行一些统计工作.但是会发现除了groupBy外,还有一个groupByKey(注意RDD也有一个groupByKey,而这里的gro ...