python 后端面试 必备必会问答大全

1、对闭包和装饰器的理解

先来介绍下 装饰器的用途,为什么要使用装饰器

假如有这么个功能,来计算耗时:


def add():

    start_time = time.time()

    time.sleep(3)

    end_time = time.time()

    print("耗时:{}".format(end_time - start_time))

    return None



if __name__ == "__main ":

    add(1, 3)


疑问:会发现,如果我有多个应用需要计时,那就需要写很多的重复代码,这时候就可以使用装饰器来操作:


# 定义一个方法,接收一个函数,在python中一切皆对象,函数也可以用来做参数赋值等


# 需要理解python装饰器加载的过程和闭包


# 新建一个test.py

import time



def time_desc(func):

    print("装饰器")

    start_time = time.time()

    func()

    end_time = time.time()

    print("耗时:{}".format(end_time - start_time))

    # return a + b



@time_desc

def add():

    

    time.sleep(3)

    

    return None


python test.py 运行后,发现函数time_desc,执行了,控制台输入了日志


装饰器

耗时:3.000149965286255

耗时:3.000149965286255


我们并没有运行 time.desc 方法,那它为什么执行了呢? 

事实证明了,在执行或者调用了这个模块里有装饰器,那python的这个@语法糖就直接运行了这个函数,所以我们才需要把

装饰器,写成闭包的形式

改写成:


import time



def time_desc(func):

    def wrapper():

        print("装饰器")

        start_time = time.time()

        func()

        end_time = time.time()

        print("耗时:{}".format(end_time - start_time))


    return wrapper  # 注意 此处不是 wrapper() 不是调用 



@time_desc

def add():

    time.sleep(3)

    return None


这就是装饰器的由来;

还有需要注意:

(1)经语法糖@装饰器后,返回的其实是wrapper,如果你调用 add() 其实是执行了装饰器 wrapper方法,

(2)如果add(a,b) 有参数的话,那装饰器 wrapper(*args, **kwargs),来解决参数问题



            
            

本博客源码Github地址:

https://github.com/whisnos/myblog

请随手给个star,谢谢!

打赏

评论