ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python:从入门到放弃 10 装饰器

2022-03-18 22:05:23  阅读:128  来源: 互联网

标签:10 函数 python inner print foo 装饰 def 入门


目录

装饰器简介

装饰器的本质:在不改变被装饰对象原有的调用方式内部代码、的情况下给被装饰对象添加新的功能

软件的设计应该遵循开放封闭原则,即对扩展是开放的,而对修改是封闭的。

软件包含的所有功能的源代码以及调用方式,都应该避免修改,否则一旦改错,则极有可能产生连锁反应,最终导致程序崩溃,而对于上线后的软件,新需求或者变化又层出不穷,我们必须为程序提供扩展的可能性,这就用到了装饰器。

装饰器

# 首先定义一个函数
def foo():
    print("foo")
    
# 如果我们需要修改它的功能
def foo():
    print("记录日志开始")
    print("foo")
    print("记录日志结束")
'''可以看见的是,我们修改了他的内部代码,这有可能导致程序崩溃'''

# 使用装饰器修改函数的功能
def outer(func): # 装饰器
    def inner():
        print("记录日志开始")
        func() # 业务函数
        print("记录日志结束")
    return inner

def foo():
    print("foo") # foo函数的内部代码没有被修改

foo = outer(foo) 
foo() # foo函数的调用方法没有被修改
'''outer 函数的返回值是 inner 函数,在 inner 函数中,除了执行日志操作,还有业务代码,该函数重新赋值给 foo 变量后,调用 foo() 就相当于调用 inner()'''

'''可以看见的是,outer函数就是一个装饰器,即装饰器是一个带有函数作为参数并返回一个新函数的闭包'''

装饰器模板

'''编写装饰器其实有一套固定的代码 不需要做任何理解'''
def outer(func_name):  # func_name用于接收被装饰的对象(函数)
    def inner(*args, **kwargs):
        print('执行被装饰函数之前 可以做的额外操作')
        res = func_name(*args, **kwargs)  # 执行真正的被装饰函数
        print('执行被装饰函数之后 可以做的额外操作')
        return res  # 返回真正函数的返回值
    return inner

语法糖

# 仅仅是让代码编写的更加好看、简洁!!!
@outer # foo = outer(foo) 省去了手动给foo重新赋值的步骤。
def foo():
    print("foo")

foo()
'''语法糖内部原理
    1.使用的时候最好紧跟在被装饰对象的上方
    2.语法糖会自动将下面紧挨着的函数名传给@后面的函数调用'''

装饰器修复技术

Python装饰器在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),而python的functools包中提供了一个叫wraps的装饰器来消除这样的副作用。它能保留原有函数的名称和注释。

from functools import wraps
def outer(func_name):
    @wraps(func_name) # 使用wraps装饰器
    def inner(*args, **kwargs):
        '''这是inner函数的注释'''
        print('执行被装饰对象之前可以做的操作')
        res = func_name(*args, **kwargs)
        return res
    return inner
@outer
def index():
    print('from index')
@outer
def home():
    '''这是home函数的注释'''
    print('from home')

help(home)
# home() 输出的是home的函数名
# 这是home函数的注释 输出的是home的注释  

如果我们将wraps装饰器注释

# from functools import wraps
def outer(func_name):
    # @wraps(func_name) # 不使用wraps装饰器
    def inner(*args, **kwargs):
        '''这是inner函数的注释'''
        print('执行被装饰对象之前可以做的操作')
        res = func_name(*args, **kwargs)
        return res
    return inner
@outer
def index():
    print('from index')
@outer
def home():
    '''这是home函数的注释'''
    print('from home')

help(home)
# inner(*args, **kwargs) 输出的是inner的函数名
# 这是inner函数的注释 输出的是inner的注释

标签:10,函数,python,inner,print,foo,装饰,def,入门
来源: https://www.cnblogs.com/RainKz/p/16023774.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有