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

2022/3/18 22:27:57

本文主要是介绍python:从入门到放弃 10 装饰器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录
  • 装饰器简介
  • 装饰器
  • 装饰器模板
  • 语法糖
  • 装饰器修复技术

装饰器简介

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

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

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

装饰器

# 首先定义一个函数
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的注释


这篇关于python:从入门到放弃 10 装饰器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程