day10闭包、函数装饰器

一、函数名的本质

  函数名本质上就是函数的内存地址、或者说函数名就是普通的变量

1、可以被赋值引用

def func1():
    print(666)

f1 = func1
f1()
        

2、可以被当作容器类型的元素

def func1():
    print(666)

def func2():
    print(222)

list = [func1,func2]
for i in list:i()

3、函数名可以当作函数参数传给函数

def func1():
    print(666)


def func3(x):
    x()

func3(func1)

二、闭包:

  闭包函数:内部函数包含对外部作用域而非全剧作用域变量的引用,该内部函数称为闭包函数。#函数内部定义的函数称为内部函数

  由于有了作用域的关系,我们就不能拿到函数内部的变量和函数了。如果我们就是想拿怎么办呢?返回呀!

  我们都知道函数内的变量我们要想在函数外部用,可以直接返回这个变量,那么如果我们想在函数外部调用函数内部的函数呢?

  是不是直接就把这个函数的名字返回就好了?

这才是闭包函数最常用的用法

def func():
    name = 'eva'
    def inner():
        print(name)
    return inner

f = func()
f()

判断闭包函数的方法__closure__

 

#输出的__closure__有cell元素 :是闭包函数
def func():
    name = 'eva'
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f = func()
f()

#输出的__closure__为None :不是闭包函数
name = 'egon'
def func2():
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f2 = func2()
f2()

 

def wrapper():
    money = 1000
    def func():
        name = 'eva'
        def inner():
            print(name,money)
        return inner
    return func

f = wrapper()
i = f()
i()
闭包嵌套

三、装饰器:

1、什么叫装饰器:

  装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。

  装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景

2、完整装饰器和装饰器的执行流程:

装饰器@的功能:   1、自动执行outer函数并将其下面的函数名func1当作参数传递
2、将outer函数的返回值返回,并重新赋值给func
def outer(func):
    def inner(*args,**kwargs):
        print('欢迎光临')
        r = func(*args,**kwargs)
        print('下次再来')
        return r
    return inner


@outer
def  func1():
    print('欧美专区')
    return 111
@outer
def func2():
    print('日韩专区')
    return 222
@outer
def func3():
    print('国产专区')
    return 333

print(func1())
print(func2())
print(func3())

 

 3、开放封闭原则:

  1.对扩展是开放的

    为什么要对扩展开放呢?

    我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

  2.对修改是封闭的

    为什么要对修改封闭呢?

    就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

    装饰器完美的遵循了这个开放封闭原则。

4、装饰器的固定格式:

def wrapper(func):
    def inner(*args,**kwargs):
        """执行被装饰函数之前的操作"""
        ret = func(*args,**kwargs)
        """执行被装饰函数之后的操作"""
        return ret
    return inner

 5、装饰器的其他改进:

def func1():
    """
    此函数是只有一个功能,观看日韩专区精彩内容,
    温馨提示:肾虚就少看
    :return: None
    """
    print('='*25)
    print('日韩专区')

print(func1.__name__)
print(func1.__doc__)

》》》

func1

    此函数是只有一个功能,观看日韩专区精彩内容,
    温馨提示:肾虚就少看
    :return: None

但是加完装饰器后怎么恢复此功能呢?

def wrapper(func):
    def inner(*args,**kwargs):
        print('',333)
        ret = func(*args,**kwargs)
        print('',555)
        return ret
    return inner

@wrapper
def func1():
    """
    此函数是只有一个功能,观看日韩专区精彩内容,
    温馨提示:肾虚就少看
    :return: None
    """
    print('='*25)
    print('日韩专区')

print(func1.__name__)
print(func1.__doc__)

》》》

inner
None
不做任何修改的效果
from functools import wraps

def wrapper(func):
    @wraps(func)
    def inner(*args,**kwargs):
        print('',333)
        ret = func(*args,**kwargs)
        print('',555)
        return ret
    return inner

@wrapper
def func1():
    """
    此函数是只有一个功能,观看日韩专区精彩内容,
    温馨提示:肾虚就少看
    :return: None
    """
    print('='*25)
    print('日韩专区')

print(func1.__name__)
print(func1.__doc__)

》》》

func1

    此函数是只有一个功能,观看日韩专区精彩内容,
    温馨提示:肾虚就少看
    :return: None
正确修改方式

6、带参数的装饰器:

flag = True

def outer(f):
    def wrapper(func):
        def inner(*args,**kwargs):
            if f:
                print('',333)
            ret = func(*args,**kwargs)
            if f:
                print('',555)
            return ret
        return inner
    return wrapper

@outer(flag)
def func1():
    print('='*25)
    print('欧美专区')
@outer(flag)
def func2():
    print('='*25)
    print('日韩专区')
@outer(flag)
def func3():
    print('='*25)
    print('国产专区')


func1()
func2()
func3()
flag = Ture   加装饰器
flag = Flase

def outer(f):
    def wrapper(func):
        def inner(*args,**kwargs):
            if f:
                print('',333)
            ret = func(*args,**kwargs)
            if f:
                print('',555)
            return ret
        return inner
    return wrapper

@outer(flag)
def func1():
    print('='*25)
    print('欧美专区')
@outer(flag)
def func2():
    print('='*25)
    print('日韩专区')
@outer(flag)
def func3():
    print('='*25)
    print('国产专区')


func1()
func2()
func3()
flag = False 不加装饰器

7、多个装饰器装饰一个函数:

def wrapper1(func):# func 就是f函数名
    def inner1():
        print('wrapper1 ,before func')#  2
        func() #   func
        print('wrapper1 ,after func')  #  4
    return inner1

def wrapper2(func):#  inner1
    def inner2():
        print('wrapper2 ,before func')#   1
        func()#  inner1
        print('wrapper2 ,after func')  #   5
    return inner2

@wrapper2  #f 最新变量 = wrapper(f)f为inner1  = inner2
@wrapper1 # f 新变量 = wrapper(f) f为函数名 = inner1
def f():
    print('in f')#   3

f() #inner2


》》》
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
View Code

 

posted @ 2018-05-11 15:30  也许VS何必  阅读(99)  评论(0编辑  收藏  举报