python学习笔记之装饰器(语法糖)

  • 什么是装饰器
  • 装饰器的知识点铺垫(函数即变量,高阶函数,嵌套函数)
  • 不带参数的装饰器示例
  • 带参数的装饰器示例
  • 作业

一、什么是装饰器

本质上,装饰器就是返回一个函数的高阶函数。装饰器就是一个函数

装饰器的原则:

  • 不修改被装饰对象的源代码
  • 不修改被装饰对象的调用方式

二、装饰器涉及的知识点

  • 函数即变量
  • 高阶函数
  • 嵌套函数

函数即变量:

在python中,一个变量首先被定义,分配内存空间,然后再使用。

以x=1,这个简单的赋值语句为例子。首先在内存中分配一个空间,x指向该内存空间,该内存空间内存入“1”

函数名本质也是一个变量,所以def test()这个语句执行后,就是在内存中分配一个空间,test指向该内存,该内存中存入函数体

代码示例:

#Author:Yueru Sun
#函数即变量
#示范一:
def foo():
    print('in the foo')
foo()
#示范二:
def bar():
    print('in the bar')
def foo():
    print('in the foo')
    bar()
foo()
#示范三:
#变量在使用的时候是先定义再使用
def foo():
    print('in the foo')
    bar()
def bar():
    print('in the bar')
foo()
#示范四:
# def foo():
#     print('in the foo')
#     bar()
#foo()#报错,因为此时bar还没有定义
# def bar():
#     print('in the bar')

特别需要注意示例三是可以执行成功的,”示例三“=”示例二“

因为在foo()执行,首先是def 了foo()和bar(),所以当执行到foo()的时候可以找到foo()和bar()

示例四是不可以执行的。因为在foo()执行之前,bar还没有在内存中定义,找不到

高阶函数:

高阶函数就是满足函数当作参数被传递或者函数的返回值是函数

嵌套函数:

def f1():
    def f2():
        def f3():
            print('from f3')
        f3()
    f2()

f1()
f3() #报错,为何?请看下一小节

还是从函数就是一个变量这个角度解释,因为f3()是在f1()内部定义的,相当于是”局部变量“,所以不能在函数外部访问到f3()

三、不带参数的装饰器示例

import time
def timer(func): #timer(test1)  func=test1
    def deco(*args,**kwargs):
        start_time=time.time()
        func(*args,**kwargs)   #run test1()
        stop_time = time.time()
        print("the func run time  is %s" %(stop_time-start_time))
    return deco
@timer  #test1=timer(test1)
def test1():
    time.sleep(1)
    print('in the test1')
test1()
#执行结果:
#in the test1
#the func run time  is 1.0033304691314697

上面的代码解释:

函数timer最本质的作用就是返回一个deco,deco是一个函数的地址空间

接下来需要理解的是@timer等价于:test1=timer(test1),timer(test1)执行之后就会返回deco,那执行test1就相当于执行了deco,即test1()=deco()

所以test1()的结果是:

in the test1
the func run time  is 1.0033304691314697

再来一个例子:

Author:Yueru Sun
import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        func(*args,**kwargs)
        end_time=time.time()
        print('func 的 运行时间是:%s'%(end_time-start_time))
    return wrapper
@timmer
def test():
    time.sleep(2)
    print('test')
test()
@timmer
def test1(number):
    time.sleep(1)
    print('func的第%s执行'%(number))
test1(1)

 

还是上面的理解过程,梳理一下执行过程:

首先是定义了timer函数,接下来执行@timer就等价于执行test1=timer(test1),执行完返回了deco,那么test1(number)=deco(number)

四、带参数的装饰器示例

如果装饰器需要传入参数,那么就在上面的基础上再嵌套一次函数

def timmer1(text):
    def out_wrapper(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            func(*args,**kwargs)
            end_time=time.time()
            print('%s func 的运行时间是%s'%(text,end_time-start_time))
        return wrapper
    return out_wrapper
@timmer1('sun')
def test2():
    print('test2')
test2()

具体的理解不赘述了,可以复习一下这个文章:

http://www.cnblogs.com/alex3714/articles/5765046.html

五、作业

编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码

猜你喜欢

转载自www.cnblogs.com/mesunyueru/p/8969897.html