当前位置: 首页 > article >正文

python语言基础-5 进阶语法-5.2 装饰器-5.2.2 简单装饰器

声明:本内容非盈利性质,也不支持任何组织或个人将其用作盈利用途。本内容来源于参考书或网站,会尽量附上原文链接,并鼓励大家看原文。侵删。

5.2.2 简单装饰器

装饰器的形式就是一个闭包,下面是一个简单的定义并使用装饰器的例子。如下:

'''
def house():
    print('我是毛坯房……')
这是一个原函数,下面我们要自定义一个装饰器,并为这个原函数添加装饰器的效果。
'''

# 定义一个装饰器
def decorate(func):  # 定义装饰器函数,它的参数是一个函数
    a = 100
    print('wrapper开始加载......')

    def wrapper():
        func()  # func()代表被装饰的原函数,使用中可根据需要放置其位置
        print('----刷漆')
        print('----铺地板', a)
        print('----做装潢')

    print('wrapper加载完成......')
    return wrapper  # 返回值是内部函数

# 定义函数并使用装饰器
@decorate  # 装饰器在定义被装饰函数时使用,自定义装饰器的名称就是我们定义装饰器函数(闭包函数)时的函数名
def house():
    print('我是毛坯房……')

# 调用函数,可以看出打印结果中带有装饰器的效果
house()

# 打印函数名查看函数的特性
print(house)  # 输出结果为<function decorate.<locals>.wrapper at 0x0000029C7675D310>,打印house,但输出wrapper,是因为装饰器装返回值给了house

由上面的例子可以看出,装饰器有如下特点:

  • 装饰器是一个闭包;
  • 装饰器以函数为参数。

为什么在被装饰器装饰后,调用原函数会有装饰效果?我们仔细考虑一下装饰器的作用过程:

  1. 装饰器的效果被打印了(上面的例子中),说明装饰器被调用了;
  2. 打印函数名显示内存地址时出现了与装饰器内层函数相关的内容(上面例子中),说明函数的地址是指向装饰器内层函数的地址的;
  3. 因此,我们可以推测:当调用原函数时,装饰器内层函数会被返回给了被装饰函数,即被装饰后装饰器的内层函数就代表了被装饰函数。

即然装饰器的内层函数代表了被装饰函数,那么需要我们考虑一种情况:当被装饰函数有参数时,装饰器的内层函数需要不需要保持参数列表的对应(不一定是一致)?答案是肯定的。如下:

'''
被装饰函数有参数,而装饰器的内层函数没有参数时,运行会报错
'''
def decorate(func):  # 定义装饰器函数
    a = 100
    print('wrapper开始加载......')

    def wrapper():  # 原函数有参,此处没有参数
        func(8)  # func(x)相当于原函数的调用,直接写定一个参数
        print('----刷漆')
        print('----铺地板', a)
        print('----做装潢')

    print('wrapper加载完成......')
    return wrapper

# 使用装饰器
@decorate
def house(n):
    print('我是毛坯房{}'.format(n))

house(3)  # 定义的原函数有参数,调用时参数是不能为空的

# 运行结果会报如下错误:TypeError: decorate.<locals>.wrapper() takes 0 positional arguments but 1 was given,这说明我们一定要给装饰器的内层函数设置参数


'''
被装饰函数有参数,装饰器的内层函数也需要参数
'''
def decorate(func):  # 定义装饰器函数
    a = 100
    print('wrapper开始加载......')

    def wrapper(*x):  # 原函数有参,因此此处也要有参,可以是单参数x,也可以是可变参数 *x
        func(x)  # func(x)相当于原函数的调用,也要有参,可以是可变参数 *x
        print('----刷漆')
        print('----铺地板', a)
        print('----做装潢{}'.format(x))

    print('wrapper加载完成......')
    return wrapper

# 使用装饰器
@decorate
def house(n):
    print('我是毛坯房{}'.format(n))

house(3)  # 定义的原函数有参数,调用时参数是不能为空的

http://www.kler.cn/a/399354.html

相关文章:

  • C++中的桥接模式
  • Ansible内置模块之known_hosts
  • ssm129办公用品管理系统开发与设计+jsp(论文+源码)_kaic
  • Failed to create a temp file - Jenkins 无法创建任务
  • 文心一言编写小球反弹程序并优化
  • 006.精读《Apache Paimon Docs - Concepts》
  • 2024年9月青少年软件编程(C语言/C++)等级考试试卷(六级)
  • JavaWeb后端开发知识储备1
  • 【HarmonyOS】鸿蒙系统在租房项目中的项目实战(一)
  • 从0开始深度学习(30)——语言模型和数据集
  • Comfy UI Manager 自定义节点管理
  • 基于卷积神经网络的航空发动机剩余寿命预测Matlab实现
  • [每周一更]-(第123期):模拟面试|消息队列面试思路解析
  • STM32 独立看门狗(IWDG)详解
  • PHP 条件语句
  • 无线迷踪:陈欣的网络之旅
  • python之openpyxl快速读取Excel表内容
  • docker:基于Dockerfile镜像制作完整案例
  • 第 17 章 - Go语言 上下文( Context )
  • Kafka简单实践
  • SpringBoot多环境配置的实现
  • 力扣 LeetCode 15. 三数之和(Day3:哈希表)
  • Java中的 File类与Files类
  • ssm131保险业务管理系统设计与实现+jsp(论文+源码)_kaic
  • leetcode hot100【LeetCode 64.最小路径和】java实现
  • MySQL一些使用操作-持续更新