装饰器python

装饰器


"""
1、什么是装饰器
    装饰器是一个用来为被装饰者添加功能的工具

    被装饰者:函数
    装饰器:可以用函数实现装饰器这种工具



2、为何要用装饰器
    为了在不修改被装饰器对象源代码以及调用方式的前提下
    为被装饰对象添加上新功能
    
    
    开放封闭原则(OCP,Open Closed Principle)是所有面向对象原则的核心。软件设计本身所追求的目标就是封装变化、降低耦合,而开放封闭原则正是对这一目标的最直接体现。其他的设计原则,很多时候是为实现这一目标服务的,例如以Liskov替换原则实现最佳的、正确的继承层次,就能保证不会违反开放封闭原则。
    
    核心思想:软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。

3、如何用装饰器

"""
# 被装饰对象
import time

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

index(111)


# # 方案一:修改了源代码
# import time
#
# def index(x):
#     start = time.time()
#     print('welcome to index page %s' % x)
#     time.sleep(3)
#     stop = time.time()
#     print(stop - start)
#
# index(111)

# # 方案二:没有修改被装饰对象的源代码与调用方式,但是有代码冗余问题
# import time
#
# def index(x):
#     print('welcome to index page %s' % x)
#     time.sleep(3)
#
# start = time.time()
# index(111)
# stop = time.time()
# print(stop - start)
#
#
# start = time.time()
# index(111)
# stop = time.time()
# print(stop - start)
#
#
# start = time.time()
# index(111)
# stop = time.time()
# print(stop - start)


# # 方案三:wrapper函数需要外部传入参数
import time

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

def wrapper():
    start = time.time()
    index(111)
    stop = time.time()
    print(stop - start)


wrapper()


# # 方案四:调用方式改变了
# import time
#
# def index(x):
#     print('welcome to index page %s' % x)
#     time.sleep(3)
#
# def wrapper(func):
#     start = time.time()
#     func(111)
#     stop = time.time()
#     print(stop - start)
#
#
# wrapper(index)


# 方案五:闭包函数
# import time
#
#
# def index(x):
#     print('welcome to index page %s' % x)
#     time.sleep(3)
#
#
# # index(111)
#
# def outter(func):
#     def wrapper(*args, **kwargs):
#         start = time.time()
#         func(*args, **kwargs)
#         stop = time.time()
#         print(stop - start)
#
#     return wrapper
#
#
# index = outter(index)  # index = wrapper的内存地址
# # print(f)
# index(111)  # wrapper(111)

# 方案五:把wrapper伪装的跟被装饰对象一样
# import time
#
#
# def index(x):
#     print('welcome to index page %s' % x)
#     time.sleep(3)
#     return 7777
#
#
# def outter(func):  # func = 地址1
#     def wrapper(*args, **kwargs):
#         start = time.time()
#         res = func(*args, **kwargs)
#         stop = time.time()
#         print(stop - start)
#         return res
#     return wrapper
#
#
# index = outter(index)  #  index = outter(地址1)  # index -> 地址2
#
# res = index(111)  # res = wrapper(111)
# print(res)

# 方案六:把wrapper伪装的跟被装饰对象一样,更进一步
import time

def index(x):
    """
    这是index的帮助信息
    """
    print('welcome to index page %s' % x)
    time.sleep(3)
    return 7777


def outter(func):  # func = 地址1
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        stop = time.time()
        print(stop - start)
        return res
    wrapper.__doc__ = index.__doc__
    wrapper.__name__ = index.__name__

    return wrapper


index = outter(index)  #  index = outter(地址1)  # index -> 地址2

# help(index)

语法糖

'''
语法糖(Syntactic sugar):
    计算机语言中特殊的某种语法
    这种语法对语言的功能并没有影响
    对于程序员有更好的易用性
    能够增加程序的可读性

'''



# 为了将装饰对象和被装饰对象一模一样,同时简化代码

def outter(func):  # func = 地址1
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        stop = time.time()
        print(stop - start)
        return res
    wrapper.__doc__ = func.__doc__
    wrapper.__name__ = func.__name__
    return wrapper


def index(x):
    """
    这是index的帮助信息
    """
    print('welcome to python %s' % x)
    time.sleep(3)
    return 7777


# 语法糖

import time
from functools import wraps


def outter(func):  # func = 地址1
    @wraps
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        stop = time.time()
        print(stop - start)
        return res
   #  wrapper.__doc__ = func.__doc__   # 这个方法不好用,函数体内置方法有很多,需要引入语法糖
    # wrapper.__name__ = func.__name__
    return wrapper
@outter   # 相当于 index = outter(index)
def index(x):
    """
    这是index的帮助信息
    """
    print('welcome to index page %s' % x)
    time.sleep(3)
    return 7777


叠加多个装饰器

# 在面对多个叠加装饰器,如何分析
def deco1(func1):
    def wrapper1(*args,**kwargs):
        print(">>>来自wrapper1")
        res1 = func1(*args,**kwargs)
        return res1
    return wrapper1

def deco2(func2):
    def wrapper2(*args,**kwargs):
        print(">>>来自wrapper2")
        res2 = func2(*args,**kwargs)
        return res2
    return wrapper2

def deco3(func3):
    def wrapper3(*args,**kwargs):
        print(">>>来自wrapper3")
        res3 = func3(*args,**kwargs)
        return res3
    return wrapper3


@deco1
@deco2
@deco3 # 1
def index():
    print('from index')
    return 123

res = index()
print(res)

# 装饰器加载顺序由下而上  ***
# 执行顺序自上而下 ****
        

有参装饰器

'''什么时有参装饰器

当内部函数需要参数时,我们想到的时构成闭包函数,为其传入参数

所以我们将其称之为有参装饰器

'''

# 

def deco(func):
    def wrapper(*args,**kwargs):
        inp_user = input("username>>>:").strip()
        inp_pwd = input("password>>>:").strip()
        if inp_user = 'wuxie' and inp_pwd == '123':
            res = func(*args,**kwargs)
            return res
        else:
            print("登录失败!!!")
        return wrapper
    
    @deco   # 语法糖 
    def index():
        print("index功能")  # 为其源函数加上认证功能
        
  '''
  新需求:当输入不同的值时,获取不同地方保存的用户信息
  '''
# 方案一
# 直接传参

def deco(func,x):
    def wrapper(*args,**kwargs):
        print(x)
        res = func(*args,**kwargs):
        return res
    return wrapper

# 此时可以完成需要,但是不能使用语法糖,语法糖的原则是只给一个参数传参

# 方案二
# 闭包函数
def outter(x,y):
    def deco(func):
        def wrapper(*args,**kwargs):
            print(x,y)
            res = func(*args,**kwargs)
            return res
        return wrapper
    return deco


# 在调用时候仍然可以使用语法糖
@outter(111,22)  # 此时触发的是 outter函数执行结果,而outter的返回值是deco,相当于@deco实现传参,同时使用语法糖,
def index():
    print('index')

index()
posted on   zhifwu  阅读(47)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示