闭包函数 装饰器

闭包函数

  顾名思义就是定义在函数内部的函数,内部函数引用了外部函数作用域的名字

def outter():
    x = 111
    def inner():
        print(x)
    return inner
res = outter()  # res就是inner函数内存地址

def func():
    x = 333
    res()
func()  # 返回的还是111 # 因为在定义阶段就已经固定了
# 补充:像inner这样虽然他的x调用的是全局的,
# 但他的y引用了外部函数名称空间作用域的名字,
# 且他是定义在函数内部的函数,
# 所以依然是满足闭包函数的两点要求的,所以也是闭包函数
x = 111 def outer(): y = 222 def inner(): print(x,y) return inner

给函数体传参有两种方式

1. 传参

  def index1(username):  # 这里的username就是变量名,也可以说是参数

  print(username)  # 这样就往函数体内传入了参数

2. 闭包

def outter(x,y):
    def my_max():
        if x > y:
            return x
        return y
    return my_max
res1 = outter(1,40)  # res1就是my_max函数的内存地址
print(res1())  # 40
print(res1())  # 40
res2 = outter(90,200)  # 这里的res2也是my_max函数的内存地址
                       # 虽然之前已经传了值了
                       # 但是在上一句代码执行结束后
                       # 关系解除,这里又建立了新的关系。
print(res2())  # 200
print(res2())  # 200
print(res2())  # 200
                

  需要注意传参和闭包的使用场景:

    1. 直接传参,可能会是在全局中定义,占用变量名,当项目较大,要传参数过多时,

      不推荐使用这个方法,只在小项目中可以使用。

    2. 闭包传参,特点是只给内部传参,在局部定义变量名,而不是全局,比较安全,起名也方便。

装饰器

  就是用来装饰的工具,就是给被装饰的对象添加新的功能,并且不改变原来的使用方法。

  装饰器的使用要遵循开放封闭原则

    开放:对扩展开放

    封闭:对修改封闭

  装饰器(装饰器也是可调用对象callable=True)必须遵循的两个原则:

    1. 不改变被装饰对象源代码

    2. 不改变被装饰对象(必须是可调用对象)调用方式

 

补充:

  # 统计函数运行时间的方法

  1.
  import time

  print(time.time())

   # 返回的是 时间戳 即当前时间距离1970-1-1 00:00:00相差的秒数 

 

  2.

  time.sleep(3)

  #让程序暂停三秒再运行

 

装饰器简单版本

  

import time
def index():
    time.sleep(3)
    print('过了三秒,我开始执行了')

def outter(func):  # func = 最原始的index函数的内存地址
    def get_time():
        start = time.time()
        func()  # func = index函数的内存地址() 直接调用
        end = time.time()
        print('index run time:%s'%(end-start))
    return get_time
index = outter(index)  # outter(最原始的index函数内存地址)
# index指向get_time函数的内存地址
index()


import time
def index01():
time.sleep(3)
print('过了三秒,我开始执行了')

def outter(func): # func = 最原始的index函数的内存地址
def get_time():
start = time.time()
func() # func = index函数的内存地址() 直接调用
end = time.time()
print('index99 run time:%s'%(end-start))
return get_time
index99 = outter(index01) # outter(最原始的index函数内存地址)
# index指向get_time函数的内存地址
index99()

 装饰器语法糖

会将紧挨着它的可调用对象的名字当做参数自动传入调用outter

  @outter      #  等价于outter(index)
  def index():
    pass

无参装饰器

    from functools import wraps
    def outter(func):
        @wraps(func)
        def inner(*args,**kwargs):  # * **在形参中使用
            # 执行被装饰函数之前你可以做的操作
            res = func(*args,**kwargs)  # * **在实参中使用
            # 执行被装饰函数之后你可以做到操作
            return res
        return inner

    @outter
    def index(username,*args,**kwargs):
        """index注释"""
        pass
    print(index)
########## 补充-重要 ##########
 wraps方法
        # 有以下两个作用
        # 1.返回原来的函数的函数名
        # 2.返回原来的函数的注释

使用方法就是
首先调用
from functools import wraps

然后在最内层函数正上方
加上 @wraps(func)

有参装饰器(最复杂就三层)

def wrappers(data):
    # data = 'file'
    def outter(func):
        def inner(*args,**kwargs):
            if data == 'file':
                # 执行被装饰函数之前你可以做的操作
                res = func(*args,**kwargs)  # * **在实参中使用
                # 执行被装饰函数之后你可以做到操作
                return res
        return inner
    return outter

装饰器的嵌套

  1. 装饰的时候,从下往上

  2.执行的时候,从上往下

@outter1  # index = outter1(func2)
@outter2  # func2 = outter2(func1)
@outter3  # func1 =  outter3(index)
def index():
    pass
posted @ 2019-07-11 18:13  Bitten  阅读(178)  评论(0编辑  收藏  举报