一.装饰器相关

1. 什么是装饰器
    器:指的是具备某一功能的工具
    装饰:指的是为被装饰器对象添加新功能

装饰器就是用来为被装饰器对象添加新功能的工具
    注意:装饰器本身可以是任意可调用对象,被装饰器的对象也可以是任意可调用对象

2. 为何要用装饰器
    开放封闭原则:封闭指的是对修改封闭,对扩展开放

装饰器的实现必须遵循两大原则:
        1. 不修改被装饰对象的源代码
        2. 不修改被装饰器对象的调用方式

装饰器的目标:就是在遵循1和2原则的前提下为被装饰对象添加上新功能

3. 怎么用装饰器

import time

def index():
    print('welcome to index page')
    time.sleep(3)

def outter(func): # func=最原始那个index的内存地址
    def wrapper():
        start=time.time()
        func() #最原始的那个index的内存地址()
        stop=time.time()
        print('run time is %s' %(stop - start))
    return wrapper

index=outter(index) #index=outter(最原始那个index的内存地址) #index=wrapper的内存地址
index() #wrapper的内存地址()

4. 装饰器升级版

import time

def index():
    print('welcome to index page')
    time.sleep(3)

def home(name):
    print('welcome %s to home page' %name)
    time.sleep(2)
    return 123

def timmer(func): #func=最原始那个home函数的内地址
    def wrapper(*args,**kwargs): #args=('egon',) kwargs={}
        start=time.time()
        res=func(*args,**kwargs) #最原始那个home函数的内地址('egon')
        stop=time.time()
        print('run time is %s' %(stop - start))
        return res
    return wrapper

# index=timmer(index)
index()

home=timmer(home) #home=outter(最原始那个home函数的内地址) #home=wrapper函数的内地址

res=home('egon') # res=wrapper函数的内地址('egon')
print(res)

二.  装饰器是语法糖

  1.  
    装饰器的语法糖:在被装饰对象正上方单独一行写@装饰器的名字
  2.  
    运行原理:
  3.  
    python解释器一旦运行到@装饰器的名字,就会调用装饰器,然后将被装饰函数的内存地址当作参数
  4.  
    传给装饰器,最后将装饰器调用的结果赋值给原函数名
  5.  
     
  6.  
    import time
  7.  
     
  8.  
    def timmer(func): #func=最原始那个home函数的内地址
  9.  
    def wrapper(*args,**kwargs): #args=('egon',) kwargs={}
  10.  
    start=time.time()
  11.  
    res=func(*args,**kwargs) #最原始那个home函数的内地址('egon')
  12.  
    stop=time.time()
  13.  
    print('run time is %s' %(stop - start))
  14.  
    return res
  15.  
    return wrapper
  16.  
     
  17.  
    @timmer #index=timmer(index)
  18.  
    def index():
  19.  
    print('welcome to index page')
  20.  
    time.sleep(3)
  21.  
     
  22.  
    @timmer #home=timmer(home)
  23.  
    def home(name):
  24.  
    print('welcome %s to home page' %name)
  25.  
    time.sleep(2)
  26.  
    return 123
  27.  
     
  28.  
    index()
  29.  
    res=home('egon') # res=wrapper函数的内地址('egon')
  30.  
    print(res)
  31.  
     

import time

# 装饰器模板
def outter(func):
    def wrapper(*args,**kwargs):
        #在调用函数前加功能
        res=func(*args,**kwargs) #调用被装饰的\也就是最原始的那个函数
        #在调用函数后加功能
        return res
    return wrapper

@outter #index=outter(index) #index=wrapper
def index():
    print('welcome to index page')
    time.sleep(3)

index()

三. 练习\认证功能装饰器

import time

def auth(func):
    def wrapper(*args,**kwargs):
        inp_user = input('please input your username: ').strip()
        inp_pwd = input('please input your password: ').strip()
        if inp_user == 'egon' and inp_pwd == '123':
            print('login successfull')
            res=func(*args,**kwargs) # 调用最原始的那个/也就是被装饰的那个函数
            return res
        else:
            print('username or password error')
    return wrapper

@auth # index=auth(index) #index=wrapper
def index():
    print('welcome to index page')
    time.sleep(3)

index() #wrapper()

四.  叠加多个装饰器

import time

def timmer(func):  #func=wrapper2
    def wrapper1(*args,**kwargs):
        start=time.time()
        res=func(*args,**kwargs)  #res=wrapper2(*args,**kwargs)
        stop=time.time()
        print('run time is %s' %(stop - start))
        return res
    return wrapper1

def auth(func): #func=最原始的那个index的内存地址
    def wrapper2(*args,**kwargs):
        inp_user = input('please input your username: ').strip()
        inp_pwd = input('please input your password: ').strip()
        if inp_user == 'egon' and inp_pwd == '123':
            print('login successfull')
            res=func(*args,**kwargs) # 调用最原始的那个/也就是被装饰的那个函数
            return res
        else:
            print('username or password error')
    return wrapper2

# 解释@语法的时候是自下而上运行
# 而执行装饰器内的那个wrapper函数时的是自上而下
@timmer # index=timmer(wrapper2) #index=wrapper1
@auth # index=auth(最原始的那个index的内存地址) #index=wrapper2
def index():
    print('welcome to index page')
    time.sleep(3)

index() #wrapper1()

import time

def outter1(func1): #func1=wrapper2
    print('outter1')
    def wrapper1(*args,**kwargs):
        print('wrapper1')
        res1=func1(*args,**kwargs) #res1=wrapper2(*args,**kwargs)
        return res1
    return wrapper1

def outter2(func2): #func2=最原始的那个index的内存地址
    print('outter2')
    def wrapper2(*args,**kwargs):
        print('wrapper2')
        res2=func2(*args,**kwargs)
        return res2
    return wrapper2

@outter1 # index=outter1(wrapper2) #index=wrapper1
@outter2 #outter2(最原始的那个index的内存地址) ===> wrapper2
def index():
    print('welcome to index page')
    time.sleep(3)

index()  #wrapper1()

'''
outter2
outter1
wrapper1
wrapper2

'''
五.  有参装饰器

import time

current_user={'username':None}

# 补充:所有的数据类型的值自带布尔值,可以直接当作条件去用,只需要记住布尔值为假的那一些值即可(0,空,None)

def login(engine='file'): #engine='mysql'
    def auth(func): #func=最原始那个index的内存地址
        def wrapper(*args,**kwargs):
            if current_user['username']:
                print('已经登录过了,无需再次登陆')
                res=func(*args,**kwargs)
                return res

if engine == 'file':
                inp_user = input('please input your username: ').strip()
                inp_pwd = input('please input your password: ').strip()
                if inp_user == 'egon' and inp_pwd == '123':
                    print('login successfull')
                    current_user['username']=inp_user # 在登陆成功之后立刻记录登录状态
                    res=func(*args,**kwargs) # res=最原始那个index的内存地址(*args,**kwargs)
                    return res
                else:
                    print('username or password error')
            elif engine == 'mysql':
                print('基于mysql的认证机制')
            elif engine == 'ldap':
                print('基于ldap的认证机制')
            else:
                print('无法识别的认证源')
        return wrapper
    return auth

@login('file')  #@auth # index=auth(最原始那个index的内存地址) #index=wrapper
def index():
    print('welcome to index page')
    time.sleep(3)

@login('file')
def home(name):
    print('welcome %s to home page' %name)
    time.sleep(2)
    return 123

index() #wrapper()
res=home('egon')
print(res)

# 有参装饰器的模板
def outter1(x,y,z):
    def outter2(func):
        def wrapper(*args,**kwargs):
            res=func(*args,**kwargs)
            return res
        return wrapper
    return outter2

# 无参装饰器的模板
def outter(func):
    def wrapper(*args,**kwargs):
        res=func(*args,**kwargs)
        return res
    return wrapper

转载于:https://www.cnblogs.com/zjh009/p/9469561.html

Python学习之路_day_11(装饰器)相关推荐

  1. Python 学习笔记9(装饰器,decorator)

    Python 学习笔记9(装饰器,decorator) 31 装饰器 装饰器可以对一个函数.方法或者类进行加工,是一种高级的python语法. 装饰函数 接收一个可调用对象作为输入参数,并返回一个新的 ...

  2. 【Python学习教程】:装饰器的详细教程,通俗易懂

    装饰器是Python中的一个重要概念,多用于在不修改原函数的基础上,为函数增加额外的功能. 基础装饰器 例如小李给女朋友买了一款iPhone12作为生日礼物,手机原封未拆封. def gift():p ...

  3. python学习必备知识点: 装饰器

    一.装饰器定义 装饰器(Decorators)是 Python 的一个重要部分.简单地说:他们是修改其他函数的功能的函数.他们有助于让我们的代码更简短. 应用场景: 假如:此时写了很多函数,有一个新的 ...

  4. Python成长之路_装饰器

    一.初入装饰器 1.首先呢我们有这么一段代码,这段代码假设是N个业务部门的函数 1 def f1(aaa): 2 print('我是F1业务') 3 if aaa == 'f1': 4 return ...

  5. python学习Day14 带参装饰器、可迭代对象、迭代器对象、for 迭代器工作原理、枚举对象、生成器及生成表达式...

    复习 函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.返回内部函数对象---->  延迟执行, 开放封闭原则: 功能可以拓展,但源代 ...

  6. python学习day-8 迭代器 生成器 装饰器

    http://www.cnblogs.com/linhaifeng/articles/7580428.html 迭代器#迭代器即迭代的工具,那什么是迭代呢?#迭代是一个重复的过程,每次重复即一次迭代, ...

  7. Python学习之路9☞面向对象的程序设计

    Python学习之路9☞面向对象的程序设计 一 面向对象的程序设计的由来 见概述:http://www.cnblogs.com/linhaifeng/articles/6428835.html 二 什 ...

  8. python 三个内置装饰器,python中自带的三个装饰器

    说到装饰器,就不得不说python自带的三个装饰器: 1.@property 将某函数,做为属性使用 @property 修饰,就是将方法,变成一个属性来使用. class A(): @propert ...

  9. python学习之路0x00

    Python学习之路0x00 在学习python之前,要知道什么是python? python是一种跨平台的计算机程序设计语言.是一种面向对象的动态类型语言,与c语言不同, c语言要编译后才能执行.而 ...

  10. 我的Python学习之路(一)_Mr_Ouyang

    我的Python学习之路(一)_Mr_Ouyang 笔者按: 本文从18:55开始写作,至19:38中断,又从21:12始继续,至23:22写就. 共计耗时113分钟,总字数9081字,约80.4字/ ...

最新文章

  1. ArcGIS中的三种查询
  2. wordpress建立php站点地图,wordpress自动网站地图
  3. boost::mpl模块实现insert_range相关的测试程序
  4. Tomcat中JVM内存溢出及合理配置(转:http://blog.csdn.net/ye1992/article/details/9344807)
  5. 组合模式源码解析(jdk+mybatis)
  6. Java二十三设计模式之------工厂方法模式
  7. Python-import导入上级 本级 目录文件
  8. [转载]GIF、JPEG 和 PNG的区别在哪里?
  9. c++ set 删除子集_Python基础数据类型「set」
  10. python实现用线程爬虫 快速高效爬数据
  11. jQuery操作cookie 的方法
  12. android中finish和system.exit方法退出的区别
  13. vs2010 vs2012 插件小番茄 visual assist x破解版下载
  14. 网课答案公众号制作教程
  15. Redux中的reducer到底是什么,以及它为什么叫reducer?
  16. SecureCRT远程操作linux系统
  17. 图解pix2pix(PatchGAN) ,pix2pixHD,vid2vid,SPADE
  18. 【跨端应用】—— uniapp黑马商城App学习笔记(二)
  19. Python下载与安装,以及下载安装编辑器Geany且通过Geany编辑运行第一个程序Hello world.
  20. 搜索不到投屏设备怎么办_电视投屏搜索不到设备解决方案

热门文章

  1. mod_signalwire.c:371 Curl Result 1, Error: Protocol https not supported
  2. 虚拟机的文件系统,是否需要碎片清理功能?
  3. 编译OpenJDK8 b232版本
  4. VS编译NPAPI:error C2733:不允许重载函数 “NP_Initialize的第二个参数
  5. 光绪变法为什么没成功
  6. NVIDIA解码器代码官方示例
  7. 多线程访问导致崩溃一例
  8. 管理感悟:忙的真正含义是没心思
  9. php 5.2 spl_autoload_register,PHP 中的__autoload() 与spl_autoload_register()函数
  10. php 按行入读文件 返回数组