专栏首页JetpropelledSnakePython入门之函数的装饰器

Python入门之函数的装饰器

本章目录:

    装饰器:

        一、为什么要用装饰器

        二、什么是装饰器

        三、无参装饰器

        四、装饰器语法糖

        五、认证装饰器实现

        六、叠加多个装饰器

        七、带参装饰器   

===========================================================

一、开放封闭原则

  引子--为什么要用装饰器

  软件一旦上线后,对修改源代码是封闭的,对功能扩展是开放的。

  也就是说我们必须找到一种解决方案:

    能够在不修改一个功能源代码以及调用方式的前提下,为其加上新功能

总结,原则如下:

      1、不修改源代码

      2、不修改调用方式

目的:

      在原则1&2的基础上扩展新功能

二、什么是装饰器

装饰器(Decorator)是一种特殊的函数,用来给函数添上新功能的函数。

  主要用于抽离大量函数中与函数本身无关的雷同代码并继续重用。

  装饰器又可分为带参数和不带参数。

  完整含义:

  装饰器即在不修改被装饰对象源代码与调用方式的前提下,为被装饰器对象添加新功能

  装饰器与被装饰对象均可以是任意可调用的对象

  装饰器>>>函数

  被装饰的对象>>>函数

三、装饰器实现之无参装饰器

  装饰器的实现不能脱离,不能修改源代码,不能修改源调用方式的原则。下面我们将按照实现装饰器的思路,一步一步实现装饰器。

  为下面的程序增加运行计时功能。

import time

def index():
    
   time.sleep()
   print('This is Index Page!')    

方案1:

import time

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()
# 该方案虽然达到了计时功能,但是修改了源代码,违背了装饰器两大原则

方案2:

import time   #引入时间包,方便调用time()方法


def index():
    time.sleep(2)
    print('This is Index Page.')


start_time = time.time()
index()
stop_time = time.time()
print('The running time is %s' % (stop_time - start_time)
# 该方案虽然达到了计时功能,但是只是针对的增加代码,如果别的程序也要计时,还要重写一次,无法复用。

方案3:

import time


def index():
    time.sleep(2)
    print('This is Index Page')


def wrapper():
  start_time = time.time()
  index()
  stop_time = time.time()   
  print('The running time is %s' % (stop_time - start_time)) 
# 该方案虽然达到了计时功能,但是要显示计时,还要去调用wrapper(),更改了原函数的调用方式

方案4:

import time


def index():
    time.sleep(2)
    print('This is Index Page')


def wrapper(func):    #func = index
    
    start_time = time.time()
    func();      #index
    stop_time = time.time()
    print('The running time is %s' % (stop_time, start_time))


wrapper(index)
# 该方案虽然达到了计时功能,但是要显示计时,不仅要调用wrapper(), 而且需要把原函数index作为参数导入,更改了原函数的调用方式

方案5(步入正轨之无参装饰器):

import time


def index():
    time.sleep()
    print('This is Index Page')


def outter(func):     # func = 最初始的index
                      # func = index    巧用闭包,传递参数,
                      # 外部函数带的参数,就是准备给内部函数里用的,这里是闭包功能
    def wrapper(): 
        start_time = time.time()
        func()
        stop_time = time.time()
        print('The running time is %s')
    return wrapper

index = outter(index)   #初始index函数经过处理已经被变更为outter(index),被''装饰''了

index()
# 该方法能显示运行时长, 是把最初始的index函数通过闭包的特点,经过处理后重新把新的函数内存地址,赋值给了index,后面的index函数已经不是最初的index,它经过被''装饰''了

  方案6(方案5的升级版):

1. 无参装饰器,引入带参函数的时候出现了错误。

# 不同于index()函数,这次我们引入一个新函数,带参数call_you(name)
import time


def call_you(name):
    time.sleep(2)
    print('I call you %s' %name)

def outter(func):
    
    def wrapper(name):
        start_time = time.time()
        res = func(name)
        stop_time = time.time()
        print('The running time is %s' % (stop_time - start_time)
        return res

    return wrapper

index = outter(index)
home = outter(home)  #home带参,但是index不带参,这里运行会报错

方案7(解决方案6的问题):

# 运用可变长度参数处理这个问题
# 可变长度参数模版,注意参数是*args  **kwargs

def outter(func):

    def inner(*args, **kwargs):
        res = func(*args, ** kwargs)
        return res

    return inner
import time


def call_you(name):
    time.sleep(2)
    print('I call you %s' %name)


def outter(func):

        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            stop_time = time.time()
            print('The running time is %s' %(stop_time - start_time))
            return res
        return wrapper


call_you = outter(call_you)

call_you('Puppy')

四、装饰器语法糖

  语法糖意指那些没有给计算机添加新功能,只是对人类来说更加“甜蜜”的语法,能够增加程序的可读性,减少代码出错的机会。

# 注意语法糖的放置位置,放在要用的函数的顶部,要用@开头

五、认证装饰器实现

  1. 加入认证模块的简单实现:

 2. 加入认证模块后登陆进行验证:

六、叠加多个装饰器

# 注意多个装饰器的顺序,按照顺序执行

1. 认证装饰器

2. 计时装饰器

3. 叠加多个装饰器(注意先后顺序)

七、带参装饰器

带参数,可以让装饰器有更大的灵活性。上面写的无参装饰器唯一的参数就是执行对应的业务函数。装饰器的语法允许我们在调用的时候,提供其他参数。新增的参数为装饰器的编写和使用提供了更大的灵活性。

上面的use_logging是允许带参数的装饰器。它实际上是对原有装饰器的 一个函数封装,并返回一个装饰器。我们可以将它理解为一个含有参数的闭包。

当我们调用的时候,Python能够发现这一层封装,并把参数传递到装饰器的环境中。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ELK学习笔记之ElasticSearch简介

    Elasticsearch (ES)是一个基于 Lucene 的开源搜索引擎,它不但稳定、可靠、快速,而且也具有良好的水平扩展能力,是专门为分布式环境设计的,E...

    Jetpropelledsnake21
  • SNMP学习笔记之Python的netsnmp和pysnmp的性能对比

    用python获取snmp信息有多个现成的库可以使用,其中比较常用的是netsnmp和pysnmp两个库。网上有较多的关于两个库的例子。

    Jetpropelledsnake21
  • Python Web学习笔记之Python多线程基础

    多线程理解 多线程是多个任务同时运行的一种方式。比如一个循环中,每个循环看做一个任务,我们希望第一次循环运行还没结束时,就可以开始第二次循环,用这种方式来节省时...

    Jetpropelledsnake21
  • CDN排障系列:curl的高级使用姿势

    curl 是一个功能非常强大的开源软件,支持FTP,HTTP,HTTPS,Telnet等多种协议。对于运维、开发同学来说,它是工作中不可缺少的排障利器。它的基本...

    淡淡的味道
  • 地球时间和 C++ 时间库

    GMT 是一个 时区,也指一种 时制。很久以前,科学家通过天文观察,将一个太阳日定义为 86400 秒,以英国 Greenwich 天文台白天平均太阳最高点作为...

    JIFF
  • Python Selenium截图功能实现代码

    砸漏
  • [Python]Matplotlib绘图基础

    1.简介 Matplotlib 是一个 Python 的 2D绘图库,它以各种硬拷贝格式和跨平台的交互式环境生成出版质量级别的图形。 ---- 2.绘图基础 2...

    昊楠Hacking
  • Python从0到1:GIL全局解释器锁

    上篇文章《Python从0到1:threading多线程编程》提及一个名词全局解释器锁GIL,很多Python爱好者私信给我说不理解它的原理,今天就对GIL单独...

    企鹅号小编
  • 6.Python装饰器

    ​ 什么是开放封闭原则?有的同学问开放,封闭这是两个反义词这还能组成一个原则么?这不前后矛盾么?其实不矛盾。开放封闭原则是分情况讨论的。

    changxin7
  • 数据结构与算法 1-5 代码执行时间测量模块timeit

    本系列是我在学习《基于Python的数据结构》时候的笔记。本小节主要介绍Python内置的代码执行时间测量模块timeit。

    触摸壹缕阳光

扫码关注云+社区

领取腾讯云代金券