Python入门学习 DAY 11 装饰器

Python入门     

DAY 11

装饰器

1. 什么是装饰器
    器:指的是具备某一功能的工具
    装饰:指的是为被装饰器对象添加新功能

    装饰器就是用来为被装饰器对象添加新功能的工具
    注意:装饰器本身可以是任意可调用对象,被装饰器的对象也可以是任意可调用对象


2. 为何要用装饰器
    开放封闭原则:封闭指的是对修改封闭,对扩展开放

    装饰器的实现必须遵循两大原则:
        1. 不修改被装饰对象的源代码
        2. 不修改被装饰器对象的调用方式

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

3. 怎么用装饰器

import time

def index():
    print('welcome to index page')
    time.sleep(3)

def outter(func): # func=最原始那个index的内存地址
    def wrapper():
        start=time.time()
        func() #最原始的那个index的内存地址()
        stop=time.time()
        print('run time is %s' %(stop - start))
    return wrapper

index=outter(index) #index=outter(最原始那个index的内存地址) #index=wrapper的内存地址
index() #wrapper的内存地址()

以上代码中index=outter(index)可以用 装饰器的语法糖实现

装饰器的语法糖:在被装饰对象正上方单独一行写@装饰器的名字
 运行原理:
 python解释器一旦运行到@装饰器的名字,就会调用装饰器,然后将被装饰函数的内存地址当作参数
传给装饰器,最后将装饰器调用的结果赋值给原函数名用法

import time

def outter(func): # func=最原始那个index的内存地址
    def wrapper():
        start=time.time()
        func() #最原始的那个index的内存地址()
        stop=time.time()
        print('run time is %s' %(stop - start))
    return wrapper

@outter
def index():
    print('welcome to index page')
    time.sleep(3)

index() #wrapper的内存地址()

装饰器模板

def outter(func):
    def wrapper(*args,**kwargs):
        #在调用函数前加功能
        res=func(*args,**kwargs) #调用被装饰的\也就是最原始的那个函数
        #在调用函数后加功能
        return res
    return wrapper

如何叠加多个装饰器(直接上代码了)

import time

def timmer(func):  #func=wrapper2
    def wrapper1(*args,**kwargs):
        start=time.time()
        res=func(*args,**kwargs)  #res=wrapper2(*args,**kwargs)
        stop=time.time()
        print('run time is %s' %(stop - start))
        return res
    return wrapper1

def auth(func): #func=最原始的那个index的内存地址
    def wrapper2(*args,**kwargs):
        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')
            res=func(*args,**kwargs) # 调用最原始的那个/也就是被装饰的那个函数
            return res
        else:
            print('username or password error')
    return wrapper2

# 解释@语法的时候是自下而上运行
# 而执行装饰器内的那个wrapper函数时的是自上而下
@timmer # index=timmer(wrapper2) #index=wrapper1
@auth # index=auth(最原始的那个index的内存地址) #index=wrapper2
def index():
    print('welcome to index page')
    time.sleep(3)

index() #wrapper1()

装饰器补充

函数还是存在着许多的内置功能,列如:_name_(获得函数名字) _doc_(获得函数内的注释),但是在使用了装饰器之后,原来的被装饰的函数最终会指向装饰器内部的函数,那就改变了原本函数的一些内容,这时我们就要注意要加载一个内部的装饰器用于将我们的装饰器内部函数伪装一下.即使用wraps 用于装饰wrapper函数,wraps起到的作用便是    # wrapper.__name__=func.__name__
                                                                                                        # wrapper.__doc__=func.__doc__

from functools import wraps
def deco(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        return res
    # wrapper.__name__=func.__name__
    # wrapper.__doc__=func.__doc__
    return wrapper

以上为本次学习内容

猜你喜欢

转载自blog.csdn.net/sql121407/article/details/81346567