【Python基础】day9——函数闭包、装饰器

装饰器

闭包

定义:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包


闭包程序示例:

def outer():
    a=1
    def inner():           #条件一:inner是一个内部函数
        print(a)           #条件二:外部环境的一个变量
    return inner           #内部函数inner就是一个闭包

outer()
print('-----')
f=outer()
f()

执行结果:

-----
1

Process finished with exit code 0

闭包=函数块+定义函数时的环境


计算代码块的执行时间示例:

import time

def foo():
    start = time.time()
    print("foo....")
    time.sleep(1)
    end = time.time()
    print('spend %s' % (end - start))

foo()

执行结果:

foo....
spend 1.0002479553222656

Process finished with exit code 0


装饰器的应用示例

装饰器应用初期示例:

import time

def foo():
    print("foo....")

def bar():
    print("bar....")

def show_time(func):                          #对于这个函数实现的功能就是计算其他函数的执行时间
    start = time.time()                      #所以我们希望传入的参数就是函数名称
    func()
    time.sleep(1)
    end = time.time()
    print('spend %s' % (end - start))
    print('next'.center(30,'-'))

show_time(foo)                                #这里在执行时间计算函数是传参函数名称即可
show_time(bar)

执行结果:

foo....
spend 1.0002162456512451
-------------next-------------
bar....
spend 1.0001883506774902
-------------next-------------

Process finished with exit code 0

 

  • 对于函数的封闭性,像上面的功能计算函数的执行时间,可以在源函数中加新的计算时间的代码,但是不建议修改原函数中的代码块,所以这里重新创建一个时间计算功能的函数,向时间计算函数中传参,参数就是其他需要计算时间的函数名称,这样就可以用一个时间计算函数计算多个函数的执行时间,没有破坏原函数的代码块,也减少了代码的冗余。

 

  • 但是上图中的程序,虽然实现了计算函数执行时间的功能,但是改变了函数的调用方式,也就是说,原来的函数调用方式是foo()但是现在的调用方式变成了show_time(foo),如果对于旧程序的修改,可能涉及到很多调用函数的地方,这时候全部修改函数的调用方式就非常的麻烦,这里建议使用下面的装饰器的方法。

 

装饰器的真实应用示例:

import time

def foo():
    print("foo....")

def bar():
    print("bar....")

def show_time(func):                           #这里使用的就是inner这个闭包,因为inner是一个闭包,可以在调用inner的时候,读取到func参数的值
    def inner():
        start = time.time()
        func()
        time.sleep(1)
        end = time.time()
        print('spend %s' % (end - start))
        print('next'.center(30,'-'))
    return inner

foo=show_time(foo)                              #再使用这里的转换
bar=show_time(bar)

foo()                                           #最终实现计算函数执行时间,同时又不改变函数的调用方式
bar()

执行结果:

foo....
spend 1.0014970302581787
-------------next-------------
bar....
spend 1.0007696151733398
-------------next-------------

Process finished with exit code 0

对以上程序的优化

import time

def show_time(func):
    def inner():
        start = time.time()
        func()
        time.sleep(1)
        end = time.time()
        print('spend %s' % (end - start))
        print('next'.center(30,'-'))
    return inner

@show_time    #等同于foo=show_time(foo)   #也是一种调用装饰器的方式
def foo():
    print("foo....")

@show_time    #等同于bar=show_time(bar)
def bar():
    print("bar....")

foo()
bar()

执行结果:

foo....
spend 1.0006310939788818
-------------next-------------
bar....
spend 1.0006492137908936
-------------next-------------

Process finished with exit code 0

装饰器实现加法器的程序代码:

import time

def show_time(func):
    def inner(x,y):
        start = time.time()
        func(x,y)
        end = time.time()
        print('spend %s' % (end - start))
        print('next'.center(30,'-'))
    return inner

@show_time
def add(a,b):
    print(a+b)
    time.sleep(1)

add(1,3)

执行结果:

4
spend 1.0006909370422363
-------------next-------------

Process finished with exit code 0


进阶:传入不定长参数

import time

def show_time(func):
    def inner(*args):
        start = time.time()
        func(*args)
        end = time.time()
        print('spend %s' % (end - start))
        print('next'.center(30,'-'))
    return inner

@show_time
def add(*args):
    sum=0
    for i in args:
        sum = sum + i
    print(sum)
    time.sleep(1)

add(1,3,9,11,98,256,199)

执行结果:

577
spend 1.000802755355835
-------------next-------------

Process finished with exit code 0

装饰器参数

  • 需求描述:用户输入参数,如果用户输入的为true,则写入日志,如果用户输入非true,则不输出日志

程序示例:

import time

def logger(flag):
    def show_time(func):
        def inner(*args):
            start = time.time()
            func(*args)
            end = time.time()
            print('spend %s' % (end - start))
            print('next'.center(30,'-'))
            if flag == 'true':
                print("log is loaded!")                  #这里使用print模拟写入日志
        return inner
    return show_time

rst=input(">>>:")
@logger(rst)
def add(*args):
    sum=0
    for i in args:
        sum = sum + i
    print(sum)
    time.sleep(1)

add(1,3,9,11,98,256,199)


执行结果:

>>>:true
577
spend 1.0006272792816162
-------------next-------------
log is loaded!

Process finished with exit code 0
>>>:false
577
spend 1.0006201267242432
-------------next-------------

Process finished with exit code 0


装饰器的作用:扩展既定函数的功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值