python装饰器详解

@[pyhton装饰器详解]
需要了解装饰器,就先要了解什么是高阶函数,什么是函数嵌套。装饰器其实就是高阶函数和函数嵌套的综合应用。
顾名思义,装饰器,就是起一个装饰的作用的方案。既不改变函数源代码、也不改变函数的调用方式,起到增加新功能的作用
如何判断一个函数它是不是装饰器,依据标准就是:不改变函数源代码、不改变函数的调用方式,又来修饰原函数的作用

一、高阶函数

简单的来讲,高阶函数就是将函数和变量联想起来,也可以这样说,函数即变量。下面我们来演示以下一个普通高阶函数的实例。

def fun1():
    print("this is fun1")
    
def fun2():
    print("this is fun2")
    
def fun(fun1,fun2):
    fun1()
    fun2()
    
fun(fun1,fun2)

我们来看一下运行结果
python装饰器详解

fun(fun1,fun2)的作用就是将fun1、fun2作为一个实参传递给fun(),在fun()内部运行fun1()和fun2()
这就是一个非常简单的高阶函数的例子。

二、函数嵌套

函数嵌套就是在一个函数的函数体里又定义了函数,可以是一个,也可以是多个。下面来看一下函数嵌套的实例。

def fun1():
    print("this is fun1")
    def fun2():
        print("this is fun2")
        def fun3():
            print("this is fun3")

三、装饰器

此前说过,装饰器就是高阶函数和函数嵌套的综合应用。现在我们来看一个实例。

import time
def text1():
    time.sleep(3)
    print('in the text1')

def text2():
    time.sleep(3)
    print('in the text2')

text1()
text2()

运行结果:
python装饰器详解

此实例功能为调用text1()和text2(),在控制台上打印相应内容。如果想要给这两个函数新加一个功能,怎么办呢?这时候就要用到装饰器了。我们先来看代码:

import time

def timer(func):
    def deco():
        start_time=time.time()
        func()
        stop_time=time.time()
        print("the func run time is ",stop_time-start_time)
    return deco   

def text1():
    time.sleep(3)
    print('in the text1')

def text2():
    time.sleep(3)
    print('in the text2')

text1=timer(text1)
text1()
text2=timer(text2)
text2()

运行后发现
python装饰器详解
确实增加了一个函数功能(计算text1()和text2()的运行时间),是不是很神奇?既没有改变函数源代码、又没有改变函数调用方式,还增加了一个新功能。这就是装饰器的雏形,到底是怎么样实现的呢?再来看一下这个实例,是不是用到了函数嵌套还有高阶函数呢?如果还对函数嵌套还有高阶函数不了解的话,同志们可以去CSDN查看一下,在这里就不再多叙了。
再回过头来看看这段代码

text1=timer(text1)
text1()
text2=timer(text2)
text2()

要是有成千上万个函数需要装饰,是不是需要下面这样写呢

text3=timer(text3)
...

当然,你也可以这样写:

import time

def timer(func):
    def deco():
        start_time=time.time()
        func()
        stop_time=time.time()
        print("the func run time is ",stop_time-start_time)
    return deco
    
@timer#语法糖 text1=timer(text1)
def text1():
    time.sleep(3)
    print('in the text1')
       
@timer
def text2():
    time.sleep(3)
    print('in the text2')

text1()
text2()

来看一下运行结果:
python装饰器详解
是不是又很神奇?和上一个运行结果一样呀!!!
在这里我们用了语法糖:@timer,其作用和text1=timer(text1)相同。是不是减少了很多工作量呢?只要想给哪个函数增加功能,就在这个函数前边加上@timer。
先不要急着开心!但是遇到带参的函数呢?就像这样子:

@timer
def text2(name):
    time.sleep(3)
    print('in the text2',name)

这该怎么办呢?话不多说,先来看解决办法:

import time

def timer(func):
    def deco(*args,**kwargs):
        start_time=time.time()
        func(*args,**kwargs)
        stop_time=time.time()
        print("the func run time is ",stop_time-start_time)
    return deco
   
@timer#语法糖 text1=timer(text1)
def text1():
    time.sleep(3)
    print('in the text1')
      
@timer
def text2(name):
    time.sleep(3)
    print('in the text2',name)

text1()
text2('mumumax')

运行结果:
python装饰器详解
在这里,我们只需要将deco()传入参量,deco(*args,**kwargs)写法可以传多参,也可以不传参,是不是方便多了?
哈哈哈,是不是get一项新技能了呢?再接着get!!
在实际开发过程中,如某网站一个页面代表一个函数,现在需要给特定的一些页面来增添新功能(如增加用户验证),该怎么样实现呢?
先来看解决方法:

import time

user,passwd="mumumax","mumumax"

def auth(func):
    def wrapper(*args,**kwargs):
        usename=input("username:").strip()
        password=input("password:").strip()
        if usename==user and password==passwd:
            print("pass the yanzheng")
            res=func(*args,**kwargs)
        else:
            exit("验证失败")
        return res
    return wrapper
        
@auth
def index():
    print("welcome to index page")
     
@auth   
def home():
    print("welcome to home page")
    return "from home"
      
@auth    
def bbs():
    print("welcome to bbs page")   
    
index()
home()
bbs()

index()为首页,home()为登陆页,bbs()为其他页。来看运行结果:

python装饰器详解
当我输入的username和password与数据库中的相匹配时,我才可以访问index()、home()、bbs(),负责会“验证失败”。
python的基本解释器就讲解到这里,如果掌握了这些东西,99%的解释器原理你都已经掌握了,剩下的1%交给实战吧,如果对我的文章感兴趣,请为我点一个赞,如果有python的知识需要了解或探讨,可以加本人微信:cuiliang1666457052

上一篇:Java初学者设计简单文本编译器


下一篇:python GUI图形界面tkinter:实现有道翻译小案例