Python闭包和装饰器

2020-04-09  本文已影响0人  学人工智能的菜菜

今天广州回暖了,不再潮湿了,阳光明媚,地球变暖,希望疫情也全部结束。

由于装饰器的本质跟闭包关系很大,所以在看装饰器之前先看闭包是什么。

闭包

一句话总结闭包:一个返回值是函数的函数
怎么理解呢?
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。

#比如打印当前时间
import time
def runtime():
    def now_time():
        print(time.time())
    return now_time
now_time = runtime()
now_time()

out:1586404291.300284
#读出一个文件中带有某个关键词的行

def make_filter(keep):
    def the_filter(file_name):
        file = open(file_name)
        lines = file.readlines()
        print(lines)
        file.close()
        filter_doc = [i for i in lines if keep in i]
        print(filter_doc)
    return the_filter

the_filter = make_filter('8')
the_filter('data.txt')
#以上则是闭包的使用,这下子是不是好理解一些了呢?
out: 
['a,b,c,d,e\n', '1,2,3,4,5\n', '6,7,8,9,10']
['6,7,8,9,10']

装饰器、语法糖、注解

由于Python的一切皆对象的原因,才有了现在的操作哈哈哈。
以下是我个人的理解:
装饰器是一个闭包,然后使用装饰器的函数作为闭包的参数传输给闭包的内函数,使用装饰器,就不需要跟闭包一样去调用闭包函数再运行内函数,直接调用装饰器的函数就可以实现这一步,由于传给装饰器的参数是函数,所以相当于可以装饰器是修改他人函数内容的函数,因为传进去被装饰的函数,所以最后闭包里的函数会有所被该函数一些数据代替。

不带参数的装饰器

#获取函数的运行时间,就跟上面一样的功能
import time
def runtime(func):
    def now_time():
        print(time.time())
        func()
    return now_time
@runtime
def student_run():
    print('学生跑')
    
student_run()#这个函数运行的时候,实际上是运行now_time函数,
out:
1586416315.0275154
学生跑

带参数的解释器

#假如我们传一个参数进去
import time
def runtime(func):
    def now_time(i):
        print(time.time())
        func(i)
    return now_time
@runtime
def student_run(i):
    print('学生跑')
    print(i)
    
student_run(1)#这个函数运行的时候,实际上是运行now_time函数,所以参数给到now_time
out:
1586416885.114295
学生跑
1

假如我们传两个参数进去

#假如我们传两个参数进去
import time
def runtime(func):
    def now_time(i,j):
        print(time.time())
        func(i,j)
    return now_time
@runtime
def student_run(i,j):
    print('学生跑')
    print(i,j)
    
student_run(1,2)#这个函数运行的时候,实际上是运行now_time函数,所以参数给到now_time
out:
1586417139.8576734
学生跑
1 2

假如我们传两个参数进去 但是如果传多个参数呢,不能一直这样子变量吧,要通用一点,所以python有一个*args接受多个参数。

#假如我们传两个参数进去 但是如果传多个参数呢,不能一直这样子变量吧,要通用一点,所以python有一个*args接受多个参数。
#假如我们传两个参数进去
import time
def runtime(func):
    def now_time(*args):
        print(time.time())
        func(*args)
    return now_time
@runtime
def student_run(*args):
    print('学生跑')
    print(args)
    
student_run(1,2)#这个函数运行的时候,实际上是运行now_time函数,所以参数给到now_time
#看到结果。
out:
1586417263.8100457
学生跑
(1, 2)

但是如果带keyword的参数怎么办呢?
python有一个**kargs接受多个参数 **代表两个元素,约定俗成的,所以可以这样子去记住。

#但是如果带keyword的参数怎么办呢?
#python有一个**kargs接受多个参数 **代表两个元素,约定俗成的,所以可以这样子去记住。
import time
def runtime(func):
    def now_time(*args,**kargs):
        print(time.time())
        func(*args,**kargs)
    return now_time
@runtime
def student_run(*args,**kargs):
    print('学生跑')
    print(args,kargs)
    
student_run(333,i=1,j=2)#这个函数运行的时候,实际上是运行now_time函数,所以参数给到now_time
out:
1586417551.9159837
学生跑
(333,) {'i': 1, 'j': 2}

日积月累,厚积薄发,循序渐进。

上一篇下一篇

猜你喜欢

热点阅读