【Python基础】装饰器(3848字)

news2024/11/19 6:23:07

文章目录

    • @[toc]
      • 闭包
      • 什么是装饰器
      • 装饰器示例
        • 不使用装饰器语法
        • 使用装饰器语法
      • 装饰器传参
      • 带参数的装饰器
      • 类装饰器
        • 魔术方法\__call__()
        • 类装饰器示例
        • 带参数类装饰器
        • property装饰器
          • 分页操作
          • 商品价格操作

因上努力

个人主页:丷从心·

系列专栏:Python基础

学习指南:Python学习指南

果上随缘


闭包

  • 在学习装饰器之前,先来了解什么是闭包:【Python基础】闭包(2157字)

什么是装饰器

  • 装饰器可以在不改变函数或类已有代码的前提下为其增加额外功能
  • 装饰器本质上是一个高阶函数,它接受一个函数或类作为输入,并返回一个新的函数或类作为输出,这个新的函数或类具有扩展或修改原始函数或类行为的功能

装饰器示例

不使用装饰器语法
def debug(func_obj):
    def wrapper():
        print(f'[DEBUG]: {func_obj.__name__}')

        func_obj()

    return wrapper


def say_hello():
    print('hello')


say_hello = debug(say_hello)
say_hello()
[DEBUG]: say_hello
hello
  • debug(say_hello)的返回值是一个函数,使用变量say_hello进行接收,于是函数say_hello()被增加了功能
使用装饰器语法
  • 装饰器通过使用@符号紧跟在函数或类定义之前来使用
def debug(func_obj):
    def wrapper():
        print(f'[DEBUG]: {func_obj.__name__}')

        func_obj()

    return wrapper


@debug
def say_hello():
    print('hello')


say_hello()
[DEBUG]: say_hello
hello
  • 本质上@debug的作用就是执行了say_hello = debug(say_hello),为函数say_hello 增加了功能

装饰器传参

  • 如果被装饰的函数带有参数,调用时需要进行传参
def debug(func_obj):
    def wrapper(*args, **kwargs):
        print(f'[DEBUG]: {func_obj.__name__}')

        func_obj(*args, **kwargs)

    return wrapper


@debug
def say(message):
    print(message)


say('Hello, world!')
[DEBUG]: say
Hello, world!

带参数的装饰器

def level(lev):
    def logger(func):
        def wrapper(*args, **kwargs):
            print(f'[{lev}]: {func.__name__}')

            func(*args, **kwargs)

        return wrapper

    return logger


@level('INFO')
def say(message):
    print(message)
[INFO]: say
Hello, world!
  • 本质上@level('INFO')的作用就是执行了say = level('INFO')(say),为函数say增加了功能
def level(lev):
    def logger(func):
        def wrapper(*args, **kwargs):
            print(f'[{lev}]: {func.__name__}')

            func(*args, **kwargs)

        return wrapper

    return logger


def say(message):
    print(message)


say = level('INFO')(say)
say('Hello, world!')
[INFO]: say
Hello, world!

类装饰器

魔术方法_call_()
  • 一个类实现了魔术方法__call__()时,当对象被调用时会自动触发__call__()方法
class Test:
    def __call__(self, *args, **kwargs):
        print('我被触发了...')


test = Test()
test()
我被触发了...
类装饰器示例
class Debug:
    def __init__(self, func_obj):
        self.func_obj = func_obj

    def __call__(self, *args, **kwargs):
        print(f'[DEBUG]: {self.func_obj.__name__}')

        self.func_obj(*args, **kwargs)


@Debug
def say(message):
    print(message)


say('Hello, world!')
[DEBUG]: say
Hello, world!
  • 本质上@Debug的作用就是执行了say = Debug(say),为函数say增加了功能
带参数类装饰器
class Logger:
    def __init__(self, level='info'):
        self.level = level

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            print(f'[{self.level}]: {func.__name__}')

            func(*args, **kwargs)

        return wrapper


@Logger(level='ERROR')
def say(message):
    print(message)


say('Hello, world!')
  • 本质上@Logger(level='ERROR')的作用就是执行了say = Logger(level='ERROR')(say),为函数say增加了功能
property装饰器
  • property装饰的方法可以看作一个实例属性,在调用时无需()
分页操作
class Page:
    def __init__(self, page_number):
        self.page_number = page_number
        self.page_size = 10

    @property
    def start(self):
        val = (self.page_number - 1) * self.page_size

        return val + 1

    @property
    def end(self):
        val = self.page_number * self.page_size

        return val


page = Page(2)

print(f'第 {page.page_number} 页, 显示第 {page.start} - {page.end} 条内容')
商品价格操作
class Goods:
    def __init__(self, ori_price):
        self.ori_price = ori_price

    @property
    def price(self):
        print('价格正在获取中...')

        return self.ori_price

    @price.setter
    def price(self, new_price):
        print('价格正在修改中...')

        self.ori_price = new_price

    @price.deleter
    def price(self):
        print('价格正在删除中...')


goods = Goods(100)

goods_price = goods.price
print(goods_price)

goods.price = 200
print(goods.ori_price)

del goods.price
  • 对被@property装饰的属性进行修改时,会触发被@price.setter装饰的方法
  • 删除被@property装饰的属性时,会触发被@price.deleter装饰的方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1663963.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis不同数据类型value存储

一、Strings redis中String的底层没有用c的char来实现,而是使用SDS数据结构( char buf[])。 缺点:浪费空间 优势: 1.c字符串不记录自身的长度,所以获取一个字符串长度的复杂度是O(N),但是SDS记录分配的长度alloc,已使用长度len,获取长度的…

资深测试必备技能!TestNG自动化测试框架实战详解

1、TestNG导言 在软件测试工作中,自动测试框架是不可或缺的,之前有Junit和Nunit框架,后有TestNG。TestNG不但吸取了Junit和Nunit框架的思想,而且创造了更强大的功能,它不但是单元测试框架,同时也是集成自动…

Qt Tab键切换焦点顺序:setTabOrder()

使用这个方法setTabOrder(),设置使得焦点的顺序从前到后依次是: ui->lineEdit》 ui->lineEdit_2》ui->lineEdit_3 》ui->lineEdit_4 焦点先在ui->lineEdit上,当按下Tab键时,焦点跑到ui->lineEdit_2上。。。按…

VS远程调试

因为是做工厂应用的客制化项目,在客户现场出现异常,本地又很难复现,而且重启软件可能又自动恢复了,此时可以用VisualStudio自带的远程调试功能进行调试,不需要重启软件,能较好的定位问题。客户电脑上不需要…

VBA信息获取与处理第四节:获取唯一非重复值返回数组的代码

《VBA信息获取与处理》教程(版权10178984)是我推出第六套教程,目前已经是第一版修订了。这套教程定位于最高级,是学完初级,中级后的教程。这部教程给大家讲解的内容有:跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互…

k8s部署skywalking(helm)

官方文档 官方文档说明:Backend setup | Apache SkyWalking官方helm源码:apache/skywalking-helm官方下载(包括agent、apm):Downloads | Apache SkyWalking 部署 根据官方helm提示,选择你自己部署的方式&#xff0c…

企业网站从传统服务器迁移到弹性云有什么优势呢?

现代企业对于网站和应用程序的可用性和性能要求越来越高,传统基础设施可能无法满足这些需求。弹性云作为一种新兴的云计算服务模式,对于企业网站的运行和管理带来了许多优势。下面是企业网站从传统服务器迁移到弹性云的五大优势: 灵活弹性&a…

【Qt 学习笔记】Qt常用控件 | 多元素控件 | Tree Widget的说明及介绍

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Qt常用控件 | 多元素控件 | Tree Widget的说明及介绍 文章编号&#x…

Unable to locate the .NET SDK

问题描述: vs2019 加载项目时,提示如下: Unable to locate the .NET SDK as specified by global.json, please check that the specified version is installed. 项目中没有globan找al.json 文件 先使用: dotnet --list-sdks 命…

使用 docker-compose 搭建个人博客 Halo

说明 我这里使用的是 Halo 作为博客的工具,毕竟是开源了,也是使用 Java 写的嘛,另外一点就是使用 docker 来安装(自动挡,不用自己考虑太多的环境因素),这样子搭建起来更快一点,我们…

SpringCloudAlibaba:5.1Sentinel的基本使用

概述 简介 Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。 官网 https://sentinelguard.io/zh-cn/ Sentinel的历史 2012 年,Sentinel 诞生,主要功能为入口流量控制。 2013-2017 年…

[ue5]编译报错:使用未定义的 struct“FPointDamageEvent“

编译报错,错误很多,但很明显核心问题是第一个:使用未定义的 struct“FPointDamageEvent“: 程序没有找到FPointDamageEvent的定义。 解决办法: 处理这类未定义都可以先F12,找到它的库位置,之后…

数据结构——快速排序

基本思想: 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,…

BMJ英国医学杂志文献去哪里下载

《柳叶刀》The Lancet、《新英格兰医学期刊》NEJM、《美国医学会杂志》JAMA、《英国医学期刊》BMJ是世界四大医学顶尖期刊,今天有位医学同学求助一篇BMJ英国医学杂志文献,下面就用这篇文献演示一下在家获取BMJ文献的方法及过程。 文献名:Sur…

Multitouch for Mac:手势自定义,提升工作效率

Multitouch for Mac作为一款触控板手势增强软件,其核心功能在于手势的自定义和与Mac系统的深度整合。通过Multitouch,用户可以轻松设置各种手势,如三指轻点、四指左右滑动等,来执行常见的任务,如打开应用、切换窗口、滚…

视频号创作分成计划实战指南:保姆级教程,带你玩转新副业

视频号的月活跃用户数量已在去年突破了8亿大关,并且不断增长。 在这篇文章中,我将与大家分享视频号的运营玩法和作品创作方向。 一、玩法流程 开通条件 要开通创作者分成计划功能,需要满足以下条件: 粉丝数量达到100及以上。 …

Python专题:十一、集合

集合的初始化 . 字符串中的重复元素只能保留一个 数学中的集合操作 - 求两个集合的差集 & 求两个集合的交集 | 合并两个集合元素

word-快速入门

1、熟悉word界面 2、word排版习惯 3、排版文本基本格式 1、word界面 选项卡 功能组 点击功能组右下角小三角可以开启完整功能组,获得启动器 软件右上角有功能显示折叠按钮 2、排版好习惯 (1)随时保存 (2)规范文件命…

矩阵相关运算1

矩阵运算是线性代数中的一个核心部分,它包含了许多不同类型的操作,可以应用于各种科学和工程问题中。 矩阵加法和减法 矩阵加法和减法需要两个矩阵具有相同的维度。操作是逐元素进行的: CAB or CA−B其中 A,B 和 C 是矩阵,且 C…

Apache Knox 2.0.0使用

目录 介绍 使用 gateway-site.xml users.ldif my_hdfs.xml my_yarn.xml 其它 介绍 The Apache Knox Gateway is a system that provides a single point of authentication and access for Apache Hadoop services in a cluster. The goal is to simplify Hadoop securit…