09 装饰器

Posted dongzhihaoya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了09 装饰器相关的知识,希望对你有一定的参考价值。

一、闭包

定义在一个函数func1内的函数func2,在返回内部函数func2时,不是单纯返回此函数的地址,还将函数中访问到的本层和上一层(非全局)名称与值的映射一起返回了。

技术分享图片

二、装饰器

1.为啥用装饰器:现在有一个函数,在程序里多次调用,后期需要给这个函数扩展功能,根据开放封闭原则:对修改封闭,对扩展开放,即可以扩展功能,加入新的代码,但不能修改原有写好的代码。所以你需要在不改变函数调用方式何不修改函数内代码的情况下,给函数增加功能。

2.什么是装饰器:所以,装饰器即给一个已有对象添加新的增强功能的工具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。

强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式

装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能

 3.装饰器的使用 

技术分享图片
import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print(run time is %s %(stop_time-start_time))
        return res
    return wrapper

@timmer
def foo():
    time.sleep(3)
    print(from foo)
foo()
无参装饰器
技术分享图片
def auth(driver=file):
    def auth2(func):
        def wrapper(*args,**kwargs):
            name=input("user: ")
            pwd=input("pwd: ")

            if driver == file:
                if name == egon and pwd == 123:
                    print(login successful)
                    res=func(*args,**kwargs)
                    return res
            elif driver == ldap:
                print(ldap)
        return wrapper
    return auth2

@auth(driver=file)
def foo(name):
    print(name)

foo(egon)
有参装饰器

4.装饰器语法

被装饰函数的正上方,单独一行
        @deco1
        @deco2
        @deco3
        def foo():
            pass

        foo=deco1(deco2(deco3(foo)))

5.装饰器补充 :wraps

from functools import wraps

def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

@deco
def index():
    ‘‘‘哈哈哈哈‘‘‘
    print(from index)
print(index.__doc__)

6.叠加多个装饰器

 1. 加载顺序(outter函数的调用顺序):自下而上

 2. 执行顺序(wrapper函数的执行顺序):自上而下

技术分享图片
def outter1(func1): #func1=wrapper2的内存地址
    print(加载了outter1)
    def wrapper1(*args,**kwargs):
        print(执行了wrapper1)
        res1=func1(*args,**kwargs)
        return res1
    return wrapper1

def outter2(func2): #func2=wrapper3的内存地址
    print(加载了outter2)
    def wrapper2(*args,**kwargs):
        print(执行了wrapper2)
        res2=func2(*args,**kwargs)
        return res2
    return wrapper2

def outter3(func3): # func3=最原始的那个index的内存地址
    print(加载了outter3)
    def wrapper3(*args,**kwargs):
        print(执行了wrapper3)
        res3=func3(*args,**kwargs)
        return res3
    return wrapper3

@outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址
@outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址
@outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址
def index():
    print(from index)

print(===========================)
index()
示范代码

 

以上是关于09 装饰器的主要内容,如果未能解决你的问题,请参考以下文章

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

类中的装饰器在Pycharm中抛出警告

thymeleaf 片段渲染后重新加载 javascript

Python面向对象学习之八,装饰器