python全栈开发-Day10 装饰器(闭合函数的应用场)

 

一、 装饰器

  装饰器就是闭包函数的一种应用场景

  什么是闭包函数?我们再来回忆一下:

  闭包函数:

    定义在函数内部的函数,并且该函数包含对外部函数作用域(强调:对全局作用域名字的引用不算闭包)名字的引用,该函数称为闭包函数

  说到作用域我们再回忆下:

  作用域:
      全局范围:内置+全局
        全局有效,全局存活
      局部范围:局部
        局部有效,局部存活
  作用域关系是在函数定义阶段就规定死,与调用位置无关,
  也就是说,无论函数在哪儿调用,都必须回到当初定义函数时的位置找作用域关系

一 、为何要用装饰器

#开放封闭原则:
    #软件一旦上线后,就应该遵循开放封闭原则,对修改源代码是封闭的,对功能的扩展是开放的,也就是我们必须找到一种解决方法:
    #能够在不修改一个功能源代码以及调用方式的前提下,为其加上新功能.

二 、什么是装饰器

#装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
#强调装饰器的原则:
    #1 、不修改被装饰对象的源代码
    #2 、不修改被装饰对象的调用方式
#装饰器的目标:
    #在遵循1和2的前提下,为被装饰对象添加上新功能

三 、装饰器的使用

#我们现在给下面函数增加一个运行时间的功能
import time

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

#修改一
def index():
    start_time=time.time()
    time.sleep(3)
    print('welcome to index page')
    stop_time=time.time()
    print('run time is %s' %(stop_time-start_time))

index()   #功能实现

#评语:直接改源代码,这么搞被开了。。。
#再来一位童靴,来实现功能
#修改二
import time

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

start_time=time.time()
index()
stop_time = time.time()
print('run time is %s' % (stop_time - start_time))

#评语:有好多函数要实现这个功能,写N遍变这个代码,
#后期维护一脸懵逼,还是被开。。。
#再来一位童靴,功能重复实现看我用强大的函数
#修订三:
import time

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

def wrapper(func):  #func=index
    start_time=time.time()
    func() #index()
    stop_time = time.time()
    print('run time is %s' % (stop_time - start_time))

wrapper(index) 

#评语:修改了原函数的调用方式,依然被开。。。
#终于来了位小牛的童靴,函数的值可以返回,然后我再把重新定义index
#修订四:
import time

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

def outter(func): #func=最原始的index
    # func=最原始的index
    def wrapper():
        start_time=time.time()
        func()
        stop_time=time.time()
        print(stop_time-start_time)
    return wrapper

index=outter(index)  # 新的index=wrapper
index()  #wrapper()  功能基本实现
#评语:在原值没有返回值是没问题,但是有返回值的情况下,这么搞就会发现返回的是None
#这次小牛牛童靴路过看到这情况,say这么搞!
#修订五
import time
def index():
    time.sleep(1)
    print('welcome to index page')
    return 123     #假使这里返回123     返回值可以是任意类型 

#==============下面就是装饰器
def timmer(func):
    #func=最原始的index
    def wrapper(*args,**kwargs):     #可变长参数
        start_time=time.time()
        res=func(*args,**kwargs)  #调用最原始的index
        stop_time=time.time()
        print(stop_time-start_time)
        return res        #index()运行的返回值
    return wrapper

index=timmer(index) # 新的index=wrapper

print(index())    #功能已经实现,返回值123

#评语:这里的装饰的功能已经实现,返回的值也得到,小牛牛不是白叫的
#天上五彩红光,大牛童靴出现!各位童靴火速围观!
import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print(stop_time-start_time)
        return res
    return wrapper

@timmer #index=timmer(index)      装饰器的标准格式!
def index():
    time.sleep(1)
    print('welcome to index page')
    return 123

@timmer # home=timmer(home)
def home(name):
    time.sleep(2)
    print('welcome %s to home page' %name)

# index()
#home('egon')   

#评语:大牛就是大牛!大牛say:教你们绝技,不会的童靴可以照下面的模板实现:

#无参装饰器模板
def outer(func):     #outer,inner名字功能随意
    def inner(*args,**kwargs):
        res=func(*args,**kwargs)
        return res
    return inner

@outer            #装饰器要在装饰函数的上方
def duoduo():
    pass                      

四 、装饰器语法

#被装饰函数的正上方,单独一行
@deco1
@deco2
@deco3
def foo():
    pass
#foo=deco1(deco2(deco3(foo)))
#这里的思想就是最上面装饰器,装饰的下面所有的函数(deco2,deco3,foo)
#然后deco2装饰(deco3,foo),最后deco3装饰foo
#功能的不同,放的顺序也要注意,不然装饰的效果可能实现的就不对了!

五、多个装饰器的使用:

import time
current_user={
    'username':None,
    # 'login_time':None
}

def auth(func):
    # func=index
    def wrapper(*args,**kwargs):
        if current_user['username']:   #这里是认证过的,下次就不用认证
            print('已经登陆过了')
            res=func(*args,**kwargs)
            return res

        uname=input('用户名>>: ').strip()
        pwd=input('密码>>: ').strip()
        if uname == 'egon' and pwd == '123':
            print('登陆成功')
            current_user['username']=uname
            res=func(*args,**kwargs)
            return res
        else:
            print('用户名或密码错误')
    return wrapper

def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print(stop_time-start_time)
        return res
    return wrapper

@timmer # timmer 统计的是auth+index的执行时间
@auth             #我们只装饰index的话就要把@timmer紧跟index
def index():
    time.sleep(1)
    print('welcome to index page')
    return 123

@auth
@timmer     #这里统计的就是home运行的时间
def home(name):
    time.sleep(2)
    print('welcome %s to home page' %name)

#index()
#home("duoduo")

六、有参数的装饰器的使用:

import time
current_user={
    'username':None,
    # 'login_time':None
}

def auth(engine):    #道理还是那个道理,在外面包了一层engine的值
    # engine='file'  #这个值外面穿什么进来就是什么
    def auth2(func):
        # func=index
        def wrapper(*args,**kwargs):
            if engine == 'file':
                if current_user['username']:
                    print('已经登陆过了')
                    res=func(*args,**kwargs)
                    return res

                uname=input('用户名>>: ').strip()
                pwd=input('密码>>: ').strip()
                if uname == 'egon' and pwd == '123':
                    print('登陆成功')
                    current_user['username']=uname
                    res=func(*args,**kwargs)
                    return res
                else:
                    print('用户名或密码错误')
            elif engine == 'mysql':         #engine 值得判断情况
                print('基于MyQL的认证')
            elif engine == 'ldap':
                print('基于LDAP的认证')
        return wrapper
    return auth2     #这里也要返回auth2的内存地址

@auth('ldap') #@auth2 #index=auth2(index) #index=wrapper
def index():
    time.sleep(1)
    print('welcome to index page')
    return 123

index() # wrapper()

python开发装饰器的应用的更多相关文章

  1. 详解Python的装饰器

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

  2. 浅谈Django的中间件与Python的装饰器

    浅谈Django的中间件 与Python的装饰器 一.原理 1.装饰器是Python的一种语法应用,利用闭包的原理去更改一个函数的功能,即让一个函数执行之前先到另外一个函数中执行其他需求语句,在执行该 ...

  3. 进阶Python:装饰器 全面详解

    进阶Python:装饰器 前言 前段时间我发了一篇讲解Python调试工具PySnooper的文章,在那篇文章开始一部分我简单的介绍了一下装饰器,文章发出之后有几位同学说"终于了解装饰器的用 ...

  4. Python 之装饰器

    Python 的装饰器可谓是提高开发效率的一大利器.然而初学装饰器的时候感觉很难理解,因为除了 Python 之外没听说哪个语言有这种东西. 而且网上看的很多解释看似容易理解,但只能很快理解了装饰器能 ...

  5. 我终于弄懂了Python的装饰器(一)

    此系列文档: 1. 我终于弄懂了Python的装饰器(一) 2. 我终于弄懂了Python的装饰器(二) 3. 我终于弄懂了Python的装饰器(三) 4. 我终于弄懂了Python的装饰器(四) 一 ...

  6. Python各式装饰器

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  7. Python札记 -- 装饰器补充

    本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...

  8. python基础——装饰器

    python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...

  9. 【转】详解Python的装饰器

    原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...

随机推荐

  1. Caused by: java.lang.ClassNotFoundException: org.hibernate.annotations.common.reflection.MetadataPro

    1.错误描述 信息: MLog clients using java 1.4+ standard logging. 2014-7-12 19:29:20 com.mchange.v2.c3p0.C3P ...

  2. OpenStack_I版 5.Nova部署

    Nova安装 创建配置存放目录,日志存放目录,执行文件目录,虚拟机目录  Nova配置修改 生成主配置文件 创建Nova数据库 同步Nova数据库 验证 Nova连接RabbitMQ配置修改  key ...

  3. Duplicate entry '0' for key 'PRIMARY'的一种可能的解决办法

    在MySQL设计好数据库往往数据库中插入数据的时候, 因为主键ID默认是不赋值的,只给其他项目赋值了,相关的SQL代码是这样的 StringBuilder strSql = new StringBui ...

  4. ThinkCMF的跳转303 404等页面的方法

    1. 控制器方法: return $this->redirect('http://www.thinkcmf.cmf',[],301); 或者助手函数: return redirect('http ...

  5. 第三篇:一个Spark推荐系统引擎的实现

    前言 经过2节对MovieLens数据集的学习,想必读者对MovieLens数据集认识的不错了:同时也顺带回顾了些Spark编程技巧,Python数据分析技巧. 本节将是让人兴奋的一节,它将实现一个基 ...

  6. 【NOIP2013】华容道(最短路)

    题目戳我 懒得粘贴题目了..就这要凑合一下吧... 题解 反正棋盘的状态不会变的... 所以,预处理一下??? 恩,如果一个棋子要移动到某个目标位置的话, 可以看成只有空格和这个子要动呀(其他的有区别 ...

  7. [ZJOI2007]时态同步

    题目描述 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数字1,2,3….进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路板的任何两个节点 ...

  8. angular+ionic+cordova(实战项目开发中,持续更新自己学到的和遇到的)

    最近公司开始准备做app了,大佬选择了angular+ionic+corvoda的开发结构,但是对于刚刚才开始对angular才有一点点感觉的我,就像是被一击闷棍敲了,半天没反应过来,emmm,怎么办 ...

  9. Centos samba 服务配置

    1背景 转到Linux有段时间了,vim操作还不能应对工程代码,之前一直都是Gnome桌面 + Clion 作开发环境,无奈在服务器上没有这样的环境, 看同事是(Windows)Source Insi ...

  10. 主库的wal日志已经被归档或异常丢失如何搭建从库

      关键字:wal日志归档  搭建从库 restore_command master 194.1 slave 194.4 wal归档目录 /backup/pgsql/pg_arch/ xlog目录 / ...