Python提高:关于闭包和装饰器

栏目: Python · 发布时间: 6年前

内容简介:闭包是指在一个函数中定义了一个另外一个函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用,这样就构成一个闭包。 例如以下:去掉了全局变量的使用。而且将 show 函数封装在了 callFunc 函数内部,使外部不可见,不能使用 show 函数,隐藏了实现细节程序在执行时,callFunc 函数返回了

闭包

闭包是指在一个函数中定义了一个另外一个函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用,这样就构成一个闭包。 例如以下:

def callFunc():
    n = 1
    def show():
        print('show: ', n)
    return show

s = callFunc()
s()复制代码

去掉了全局变量的使用。而且将 show 函数封装在了 callFunc 函数内部,使外部不可见,不能使用 show 函数,隐藏了实现细节

程序在执行时,callFunc 函数返回了 内部定义 的 show 函数,并且 在 show 函数 内部使用 了外部函数的变量。

在 show 函数返回时,保存了当前的执行环境,也就是会在 show 函数中使用的外部变量 n 。

因为 n 是一个 callFunc 函数中的局部变量,正常情况下 callFunc 函数执行结束后,n 就会被释放。

但是现在因为 callFunc 函数中返回了 show 函数,show 函数在外部还会再执行,所以程序会将 show 函数所需的执行环境保存下来。

这种形式就是闭包。

装饰器

装饰器本身也是一个函数 ,作用是为现有存在的函数,在不改变函数的基础上去增加一些功能进行装饰。

装饰器实际上就是一个函数 ,这个函数以闭包的形式定义使用 @装饰器函数名 形式来装饰。

比如现在一个项目中,有很多函数 ,由于项目越来越大,功能越来越多,导致程序越来越慢。

其中一个功能函数功能,实现一百万次的累加。

def my_count():
    s = 0
    for i in range(1000001):
        s += i
    print('sum : ', s)复制代码

现在想计算一下函数的运行时间,如何解决?如何能应用到所有函数上?

解决办法:

import time

def count_time(func):
    def wrapper():      #wrapper 装饰
        start = time.time()
        func()
        end = time.time()
        print('共计执行:%s 秒'%(end - start)) # 使用%d显示,取整后是0秒,因为不到一秒
    return wrapper

@count_time     # 这实际就相当于解决方法3中的 my_count = count_tiem(my_count)
def my_count():
    s = 0
    for i in range(10000001):
        s += i
    print('sum : ', s)

my_count()复制代码

这样实现的好处是,定义好了闭包函数后。只需要通过 @xxx 形式的装饰器语法,将 @xxx 加到要装饰的函数前即可。

万能装饰器

def setFunc(func):
        def wrapper(*args, **kwargs):   # 接收不同的参数
            print('wrapper context')
            return func(*args, *kwargs) # 再原样传回给被装饰的函数

        return wrapper

    @setFunc
    def show(name, age):
        print(name,age)

    show('tom',12)
复制代码

通过可变参数和关键字参数来接收不同的参数类型。

类实现装饰形式

通过类的定义也可以实现装饰器形式。

在类中通过使用 __init__ 和 __call__方法来实现

class Test(object):
        # 通过初始化方法,将要被装饰的函数传进来并记录下来
        def __init__(self, func):
            self.__func = func
        # 重写 __call__ 方法来实现装饰内容
        def __call__(self, *args, **kwargs):
            print('wrapper context')
            self.__func(*args, **kwargs)


    # 实际通过类的魔法方法call来实现
    @Test  # --> show = Test(show) show由原来引用函数,装饰后变成引用Test装饰类的对象
    def show():
        pass


    show()  # 对象调用方法,实际上是调用魔法方法call,实现了装饰器复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Applications (Hacking Exposed)

Web Applications (Hacking Exposed)

Joel Scambray、Mike Shema / McGraw-Hill Osborne Media / 2002-06-19 / USD 49.99

Get in-depth coverage of Web application platforms and their vulnerabilities, presented the same popular format as the international bestseller, Hacking Exposed. Covering hacking scenarios across diff......一起来看看 《Web Applications (Hacking Exposed)》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器