python:从闭包到装饰器

首先来看一下,简单的闭包函数:

def func(x):
    def func1():
        return x
    return func1

>>g = func(3)
>>g()

>>3

1.内部函数可以对外部函数的变量进行操作

2.外部函数返回内部函数对象

满足以上两点,即是闭包

在上例中,外部函数变量x,被传入到内部函数func1中并返回,外部函数func返回内部函数的函数对象func1

函数对象加上()才为调用,否则只是函数对象,python万物皆对象

接下来,来看一下,内部函数带有参数的闭包

def func2(x):
    def func3(y):
        return x+y
    return func3

>>g = func2(2)
>>g(3)

>>5

思考:当g = func2(2)执行完时,func2已经结束了,那么为什么x = 2实际上在g(2)还起作用呢?

因为当x = 2传入func2时,内部函数保留了这个实参

可以对代码做微小修改来表现:

def func2(x):    #step1
    #step2:
    def func3(y): #step6
        print(x) 
        return x+y#step7
 
    return func3  #step3

>>g = func2(2) #step4
>>g(3) #step5

>>2
>>5

​

结合“函数对象可以作为函数参数”的特性,因此,这里的完全可以被赋值为一个函数对象,这是func2就成为了传入函数的装饰器

#一个输出函数__name__属性的装饰器

def printname(func):
    def swarps(*args,**kwargs): #被修饰函数的参数将会成为内部函数的参数

        print(func.__name__) #装饰器的意义在于此

        return func(*args,**kwargs) #执行原被修饰的函数,不然原函数的结果不会返回

    return swarps #返回函数对象

@printname
def square(x):
    return x**2

square(2)
>>square 
4


#将装饰器函数与闭包函数做比较
def printname(func):                                    def func(x):
    def swarps(*args,**kwargs):                             def func1(y):
        print(func.__name__)         <<#对外部参数操作>>          print(x+2)
        return func(*args,**kwargs)  <<#对内外部函数一起做操作>>   return x+y 
    return swarps                    <<#返回内部函数对象>>    return func1

@printname                                       
def square(x):                 g = func(3) >> g(2) == func(3)(2)
    return x**2

#装饰器printname的执行过程
step1:将函数对象square传入printname的形参func
step2:在printname内部定义一个函数swarps并返回swarps,即printname(square) >>swarps
step3:x作为返回的函数对象swarps的参数,相当于执行swarps(x)
step4:执行swarp(x),并返回原函数的执行结果(return func(*args,*kwargs)一句,如果没有这一句,原函数的执行结果将被覆盖)

func(x)(y) >>printname(square)(x) 其实就是这样这样一种对应关系啦

函数名作为外部参数,函数参数作为内部参数的一个闭包而已,懂了吗?

下一个知识点:

带参数的装饰器,实际上就是对装饰器函数进行封装,举例来说,同样是刚才的printname装饰器

#一个简单的带参数装饰器
#对printname装饰器添加参数,要求当password = 5的时候才执行装饰器
def addargument(password):
    def printname(func):
        def swarps(*args,**kwargs):
            if password == '5':
                print(func.__name__)
                return func(*args,**kwargs)
        return swarps
    return printname

@addargument(5)
def square(x):
    return x**2

关于类装饰器,等学完了类和对象再来写吧

发布了15 篇原创文章 · 获赞 2 · 访问量 3828

猜你喜欢

转载自blog.csdn.net/KageYamaa/article/details/81535670
今日推荐