Python 闭包和装饰器的讲解

1, 闭包。

一、定义说明:
在Python中,函数内部可以定义函数(函数名其实就是指向一段内存空间的地址,即函数名就是函数的入口地址)。
闭包函数必须满足两个条件: 1.函数内部定义的函数 2.包含对外部作用域而非全局作用域的引用。
例1:
def a(a, b):
    def c(x):
        return a*x + b
    print(c.__closure__)
    return c
# 调用
print(a(3, 4)(8))
二、优缺点说明
1、实现了代码的可复用性
2、闭包似优化了变量,原来需要类对象完成的工作,闭包也可以完成
3、由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存(闭包调用时候,如果内部函数没有调用,其内存资源得不到释放。)

2,装饰器

一、定义
装饰器:外部函数传入被装饰函数名,内部函数返回装饰函数名。
特点:1.不修改被装饰函数的调用方式 2.不修改被装饰函数的源代码
python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用修改原函数的代码前提下给函数增加新的功能。其实通俗一点讲,其实装上器就是闭包的功能的扩展。
举例:
def w1(func):
    def inner():
        # 验证1
        # 验证2
        # 验证3
        func()
    return inner
@w1
def f1():
    print('f1')
简单的运行原理:
在调用f1函数时,其实通过@w1(语法糖)将f1(函数入口地址传递给w1函数的参数func,并将w1的返回值传递给原来的f1所在的位置。),那么执行函数f1时,其实就是执行了w1(f1)(),这样就实现在没有改变原来代码的情况下,扩展了原来的功能,而且没有改变原来的函数名。
二、多个装饰器。
def makeBold(fn):
    def wrapped():
        return "<b>" + fn() + "</b>"
    return wrapped
def makeItalic(fn):
    def wrapped():
        return "<i>" + fn() + "</i>"
    return wrapped
@makeBold
@makeItalic
def test3():
    return "hello world-3"
print(test3())
运行结果:<b><i>hello world-3</i></b>
原理和上面就讲解的一样,不再赘余。
三、带关于带参数的装饰器。
1、第一种(一般参数)
def timefun(func):
    def wrappedfunc(a, b):
        print(a, b)
        func(a, b)
    return wrappedfunc
@timefun
def foo(a, b):
    print(a+b)
foo(8, 9)
输出结果:
8 9
17
2、第二种(不定长参数)。
def timefun(func):
    def wrappedfunc(*args, **kwargs):
        func(*args, **kwargs)
    return wrappedfunc
@timefun
def foo(a, b, c):
    print(a+b+c)
foo(3,5,7)
运行结果:
15
3、有返回值
def timefun(func):
    def wrappedfunc():
        print(5445)
        return func()
    return wrappedfunc
@timefun
def getInfo():
    return '----hahah---'
print(getInfo())
结果:
5445
----hahah---
4、在原有的基础上在添加参数。
def timefun_arg(pre="hello"):
    def timefun(func):
        def wrappedfunc():
            print(pre)
            return func()
        return wrappedfunc
    return timefun
@timefun_arg("dcg")
def foo():
    print("I am foo")
foo()
5、类装饰器
(主要重写__call__方法。)
对__call__方法进行讲解:
class Foo(object):
    def __init__(self, func):
        self._func = func
    def __call__(self):
        print('class decorator runing')
        self._func()
        print('class decorator ending')
@Foo  # bar = Foo(bar)
def bar():
    print('bar')
bar()  # Foo(bar)()
# 结果
# class decorator runing
# bar
# class decorator ending

猜你喜欢

转载自blog.csdn.net/MZP_man/article/details/92571576