博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python-装饰器的简单使用
阅读量:6913 次
发布时间:2019-06-27

本文共 3164 字,大约阅读时间需要 10 分钟。

一、介绍

首先我们先来看一个简单的例子,在基础平台中有一个home()和tv()函数,在业务平台中调用此函数时,给出了响应的打印内容:

基础平台:def home():    print('welcome to home page')def tv(name):    print('welcome to tv page')业务平台A: home()tv()业务平台B:home()tv()

    

但是,在后续的需求中规定,在调用此函数时,还需要进行一个用户验证

因此程序猿小A的做法是和每个业务部门交涉,每个业务部门自己写代码,在调用基础平台的时候,先进行验证:

基础平台:def home():    print('welcome to home page')def tv(name):    print('welcome to tv page')业务平台A: #验证home()tv()业务平台B:#验证home()tv()

小A当天被开除了。。。

 

后来程序猿小B接手了这份工作,小B的做法是在基础平台中加入验证:

基础平台:def home():    #验证    print('welcome to home page')def tv(name):    #验证    print('welcome to tv page')业务平台A: home()tv()业务平台B:home()tv()

小B的做法相比于小A来说,好了一点,避免了业务平台的修改,老板为了奖励小B,因此在一周后把小B开除了。。。

因为小B改动了源代码

 

此后,程序猿小C又接受了这个工作。。。

小C说:

写代码要满足以下下两个原则:

  封闭:已实现的功能代码不允许被修改

  开放:已实现的功能代码可以被扩展:

因此,小C打算在此处使用了装饰器的功能(见下文)

 

总结:

装饰器本质上是一个函数,可以在其他函数不做任何代码变动的情况下,提供一些扩展的功能

 

 

二、简单装饰器的使用

小C对代码做出了如下修改(拿tv方法举例):

 

def login(func):                   #定义了一个登录验证的方法           print('登录验证成功')            #假设此处就是一个验证功能    return func                    def tv():    print('welcome to tv page' )tv=login(tv)                       #对tv进行了赋值,此时还没执行tv方法,只是把该方法放入到了内存中 tv()---执行结果---登录验证成功welcom to tv page

 

该代码是如何实现验证的呢,步骤如下:

  ①执行login(tv)时,先不执行tv()方法,只是把tv()方法到了内存中,然后执行login()

  ②在login()中进行登录验证,之后返回tv()的内存地址,此时tv()还未执行

  ③把tv()的内存地址重新赋值给tv,此时tv变量的值依旧为tv()方法的内容

  ④通过调动tv()执行tv()方法

 

再经过一些细小的调整,可以写成如下的形式:

def login(func):                            print('登录验证成功')    return func                    @logindef tv():    print('welcome to tv page' )                    tv()

 

 

其中, @XXX  语法,就是一个装饰器,也称为“语法糖”

至此,一个简单的装饰器雏形已经完成

 

但是,此处依旧有一个缺点,那就是 即使业务方没有调用tv(),代码中也依旧会执行login()中的验证,为了让login()中的验证

不预先执行,因此小C继续对代码进行调整

def login(func):    def inner():        print('登录验证成功')        func()    return inner@login       def tv():    print('welcome to tv page' )tv()

此处实现验证功能的步骤如下:

  ①调用login()方法,返回inner方法的内存地址,此时func的值为tv()内存地址即内容为:

def tv():           print('welcome to tv page' )

  ②把inner方法的内存地址赋值给了变量tv

  ③调用tv(),因为tv的值已经为inner的内存地址,因此调用的是inner()方法

  ④实现inner()中的验证功能

  ⑤验证成功后,执行inner()中的func(),打印出‘welcome to tv page’

至此,一个简单的装饰器才算真正完成

 

如果想在调用方法中实现带参数,可以这样写:

def login(func):    def inner(arg):        print('登录验证成功')        func(arg)    return inner@logindef tv(name):    print('welcom to [%s] tv page' %name )@logindef movie(name):    print('welcom to [%s] movie page' %name )tv('nee')movie('nee')-----结果-----登录验证成功welcom to [nee] tv page登录验证成功welcom to [nee] movie page

在上面的例子中,都是实现了在调用tv()和movie()时带入一个参数的情况的。但如果在调用tv()时需要一个参数,在调用movie()时用两个参数呢?

因此可以使用一个动态参数的方法:

def login(func):    def inner(*args):                #代表动态参数        print('登录验证成功')        func(*args)    return inner@logindef tv(name,password):    print('welcom to [%s] tv page' %name )@logindef movie(name):    print('welcom to [%s] movie page' %name )tv('nee',123456)movie('nee')

  

 如果再进一步,想要在调用tv()方法后,打印一个结果

def login(func):    def inner(*args,**kwargs):        print('登录验证成功')        return func(*args,**kwargs)        #注意此处的return    return inner@logindef tv(name,password):    print('welcom to [%s] tv page' %name )    return '我最帅'a=tv('nee',password=123456)print(a)-----结果-----登录验证成功welcom to [nee] tv page我最帅

  

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/nizhihong/p/7073512.html

你可能感兴趣的文章
windows下查看特定端口被什么程序占用
查看>>
JSON.parse()与JSON.stringify()的区别
查看>>
1032. Sharing (25)
查看>>
JSP的隐藏对象
查看>>
2014秋C++ 第8周项目 分支程序设计
查看>>
[pig] pig 基础使用
查看>>
java中的线程同步
查看>>
Does the parameter type of the setter match the return type of the getter?
查看>>
MongoDB count distinct group by JavaAPI查询
查看>>
Java多线程系列——原子类的实现(CAS算法)
查看>>
LibEvent代码阅读--多缓冲区和零拷贝技术
查看>>
学生管理系统报错(一)
查看>>
使用 Live555 搭建流媒体服务器
查看>>
第十四周(OOP版电子词典)
查看>>
网络基础知识小小说
查看>>
linux lsof命令详解
查看>>
POJ 1163 The Triangle【dp+杨辉三角加强版(递归)】
查看>>
vue如何在路由跳转的时候更新组件
查看>>
Java多线程(二)
查看>>
《深入浅出数据分析》读后具体解释
查看>>