装饰器

Posted xufengnian

tags:

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

1.什么是装饰器

  器:指的是具备某一功能的工具

  装饰:指的是为被装饰器对象添加新功能

 

  装饰器就是用来为被装饰器对象添加新功能的工具

  注意:装饰器本身可以是任意可调用对象,被装饰器的对象也可以是任意可调用对象

2.为何要用装饰器

  软件的开发要遵循一个原则,开放封闭原则。

  开放封闭原则:软件实体应该对扩展开放,对修改关闭,其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。

  遵循开放封闭原则的话,则必须要使用到装饰器

  装饰器的实现必须遵循两大原则:

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

    2.不修改被装饰对象的调用方式

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

3.怎么使用装饰器

这里写了一个简单的统计执行时间的装饰器

技术分享图片
import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start=time.time()
        res=func(*args,**kwargs)
        end=time.time()
        print(end-start)
        return res
    return  wrapper

@timmer
def index(name):
    print(welcome to %s %name)
    time.sleep(2)

index(shanghai)
View Code

装饰器模板

def timmer(func): 
    def wrapper(*args,**kwargs): 
        #被装饰函数执行前干些什么
        res=func(*args,**kwargs) #被装饰函数开始执行
        #被装饰函数执行后干些什么
        return res
    return wrapper

装饰器的语法糖

在被装饰对象正上方单独一行写@装饰器的名字

运行原理:

python解释器一旦运行到@装饰器的名字,就会调用装饰器,然后将装饰函数的内存地址当做参数传给装饰器,最后将装饰器调用的结果赋值给原函数名

 

叠加多个装饰器

解释@语法的时候是自下而上运行

而执行装饰器内的那个wrapper函数时是自上而下

技术分享图片
import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start=time.time()
        res=func(*args,**kwargs)
        end=time.time()
        print(end-start)
        return res
    return wrapper
def outer(func):
    def wrapper(*args,**kwargs):
        res=func(*args,**kwargs)
        print(func)
        time.sleep(1)
        return res
    return wrapper

@outer
@timmer
def index(name):
    print(welcome to %s %name)
    time.sleep(2)

index(shanghai)
View Code

有参装饰器

技术分享图片
import time
current_user={username:None}
# 补充:所有的数据类型的值自带布尔值,可以直接当作条件去用,只需要记住布尔值为假的那一些值即可(0,空,None)
def login(engine=file): #engine=‘mysql
    def auth(func): #func=最原始那个index的内存地址
        def wrapper(*args,**kwargs):
            if current_user[username]:
                print(已经登录过了,无需再次登陆)
                res=func(*args,**kwargs)
                return res
            if engine == file:
                inp_user = input(please input your username: ).strip()
                inp_pwd = input(please input your password: ).strip()
                if inp_user == egon and inp_pwd == 123:
                    print(login successfull)
                    current_user[username]=inp_user # 在登陆成功之后立刻记录登录状态
                    res=func(*args,**kwargs) # res=最原始那个index的内存地址(*args,**kwargs)
                    return res
                else:
                    print(username or password error)
            elif engine == mysql:
                print(基于mysql的认证机制)
            elif engine == ldap:
                print(基于ldap的认证机制)
            else:
                print(无法识别的认证源)
        return wrapper
    return auth

@login(file)  #@auth # index=auth(最原始那个index的内存地址) #index=wrapper
def index():
    print(welcome to index page)
    time.sleep(3)

@login(file)
def home(name):
    print(welcome %s to home page %name)
    time.sleep(2)
    return 123


index() #wrapper()
res=home(egon)
print(res)

# 有参装饰器的模板
def outter1(x,y,z):
    def outter2(func):
        def wrapper(*args,**kwargs):
            res=func(*args,**kwargs)
            return res
        return wrapper
    return outter2
View Code

 

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

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

thymeleaf 片段渲染后重新加载 javascript

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

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

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

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