python 学习笔记7(装饰器)

闭包(closure)是函数式编程的重要的语法结构。

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

def outer():                               
    x = 1                                    
    def inner():                                       
        print(x)                                     
    return inner                               
f = outer()                                
f()                  

inner就是内部函数,inner里引用了外部作用域的变量x(x在外部作用域outer里面,不是全局作用域),则这个内部函数inner就是一个闭包。

闭包=函数块+定义函数时的环境,inner就是函数块,x就是环境。

装饰器

  装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。

  它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能

简单的装饰器函数:

@符号是装饰器的语法糖,在定义函数的时候使用,避免再一次赋值操作

import time
def shoe_time(f):
    def inner():
        start = time.time()
        f()
        end = time.time()
        print(end-start)
    return inner
@shoe_time   #foo = shoe_time(foo)
def foo():
    #start = time.time()
    print("foo......")
    time.sleep(2)
    #end = time.time()
    #print(end-start)               #2.0001144409179688
#foo()
@shoe_time     #bar = shoe_time(bar)
def bar():
    # start = time.time()
    print("bar......")
    time.sleep(3)
    #end = time.time()
    #print(end-start)                #3.001171588897705
#bar()
#shoe_time(foo)              #2.0001142024993896
#shoe_time(bar)                #3.001171588897705
foo()                      #foo......                           # 2.0001144409179688
bar()                       # bar......
                          # 3.00017142295837

带参数的被装饰函数

#功能函数加参数
import time
def shoe_time(f):
     def inner(x,y):
         start = time.time()
         f(x,y)
         end = time.time()
         print(end-start)
     return inner
@shoe_time
def add(a,b):
    print(a+b)
    time.sleep(3)
#@shoe_time
# def foo():
#     print("foo......")
#     time.sleep(2)
# @shoe_time
# def bar():
#      print("bar......")
#      time.sleep(3)
#
add(1,3)       #4
               #3.000171661376953


#不定长参数
import time
def shoe_time(f):
     def inner(*x,**y):
         start = time.time()
         f(*x,**y)
         end = time.time()
         print(end-start)
     return inner
@shoe_time
def add(*a,**b):
    sum = 0
    for i in a:
        sum += i
    print(sum)
    time.sleep(3)
#@shoe_time
# def foo():
#     print("foo......")
#     time.sleep(2)
# @shoe_time
# def bar():
#      print("bar......")
#      time.sleep(3)
#
add(1,3,4,6,78)              #92
                             #3.000171661376953

带参数的装饰器

  装饰器还有更大的灵活性,例如带参数的装饰器:在上面的装饰器调用中,比如@shoe_time,该装饰器唯一的参数就是执行业务的函数。装饰器的语法允许我们在调用时,提供其它参数,比如@decorator(a)。这样,就为装饰器的编写和使用提供了更大的灵活性。

#带参数的装饰器

import time
def logger(flag=""):
    def shoe_time(f):
         def inner(*x,**y):
             start = time.time()
             f(*x,**y)
             end = time.time()
             print(end-start)
             if flag == "true":
                 with open("日志记录", "a",encoding="utf8") as g:
                     g.write("值为: %s 时间为: %s
"%(f(*x),(end-start)))
         return inner
    return shoe_time
@logger("true")     #@show_time
def add(*a,**b):
    Sum = 0
    for i in a:
        Sum += i
    print(Sum)
    time.sleep(3)
    return Sum
@logger("abc")
def foo():
    print("foo......")
    time.sleep(2)
# @shoe_time
# def bar():
#     print("bar......")
#     time.sleep(3)

add(1,3,4,6,78)      #92
                    #3.000171661376953
foo()

  @logger("true") 做了两件事:

    (1)@ogger("true"):得到闭包函数show_time,里面保存环境变量flag

    (2)@time   :add=show_time(add)

上面的logger是允许带参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器(一个含有参数的闭包函数)。当我 们使用@logger("true")调用的时候,Python能够发现这一层的封装,并把参数传递到装饰器的环境中。

 
原文地址:https://www.cnblogs.com/lst1010/p/5851643.html