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

文章目录

    • @[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装饰的方法

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从0开始学python(七)

目录 前言 1 break、continue和pass函数 1.1 break 1.2 continue 1.3 pass 2、序列的索引及切片操作 2.1字符串的索引和切片 2.1.1 字符串索引 2.1.2 字符串切片 总结 前言 上一篇文章我们介绍了python中的循环结构,包括for和while的使用。本章接着往下讲。…

中仕公考:要报深圳教师编的考生们要注意了,往届、应届都可报!

2024上半年广东深圳市(区)属公办中小学教师招聘公告已发布 5月13日10:00至5月17日17:00报名,6月2日笔试。

基于SSM+Vue的物流管理系统

运行截图 获取方式 Gitee仓库

智慧公厕解决了什么问题?

在现代城市生活中,公厕是一个不可忽视的环节。然而,过去的公共厕所常常存在管理不力、环境脏乱差等问题,给人们的生活带来了许多不便和困扰。为了解决这些问题,智慧公厕应运而生,成为了公共厕所使用、运行、管理、养护…

Linux-进程管理类命令实训

实训1:进程查看,终止,挂起及暂停等操作 1.使用ps命令显示所有用户的进程 2.在后台使用cat命令。查看进程cat,并杀死进程 3.使用top命令只显示某一用户的进程。 4.执行命令cat,把Ctrlz挂起进程,输入jobs命令…

Excel办公技巧之下拉菜单

在日常办工中,经常需在单元格中输入特定的值,此时我们可以使用下拉菜单解决,输入错误和错误值,可以一劳永逸的解决固定数据输入问题。 使用Excel下拉菜单时,它在数据输入和验证方面发挥着重要作用通过点击单元格的下拉…

时序分解 | Matlab实现LMD局域均值分解

时序分解 | Matlab实现LMD局域均值分解 目录 时序分解 | Matlab实现LMD局域均值分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 时序分解 | Matlab实现LMD局域均值分解 Matlab语言 1.算法新颖小众,用的人很少,包含分解图 2.直接替换数据即可用…

iOS 安装cocoapds

注意 CocoaPods安装是基于ruby环境的,所以要安装CocoaPods先要安装Ruby环境,国内不能直接安装,只能通过VPN或淘宝的Ruby镜像来访问。 安装过程 gem sources --remove https://rubygems.org/ ** (注意是两个“-”,否则会移除失败) …

【分立元件】一起读读10/100 Base-T网络变压器规格书

网络变压器亦称为网络隔离变压器或数据泵。广泛应用于太网交换机、路由器、网络机顶盒、智能电视、网络摄像机、网络刻录机、笔记本电脑、无线AP、智能网关等设备,起到信号耦合、高压隔离、阻抗匹配、波形修复、电磁干扰抑制等作用。 下面我们一起读一读网络变压器规格书,来看…

计算机网络实验3:路由器安全防控配置

实验目的和要求 理解标准IP访问控制列表的原理及功能理解CHAP、DHCP配置原理了解家用式无线路由配置方法实验项目内容 标准IP访问控制列表配置 CHAP验证路由器上配置DHCP网络地址转换NAT配置无线路由实现实验环境 1. 硬件:PC机; 2. 软件:W…

CCPD车牌检测识别数据集

CCPD 是一个在开源免费的中国城市车牌识别数据集。 1. 介绍 CCPD (Chinese City Parking Dataset, ECCV)是中国城市车牌数据集,共有两个CCPD2019和CCPD2020 数据集,总数据量约35W左右,可用于车牌检测和识别模型算法开发。 CCPD 发表的论文:…

该从哪些方面提升系统的吞吐量?

更多大厂面试内容可见 -> http://11come.cn 该从哪些方面提升系统的吞吐量? 我们平时自己做的项目一般没有用户量,都是练手项目,所以并不会在吞吐量上做出很多的优化,但是这样的话,又会导致项目和其他人相比并没有…

找不到d3dx9_42.dll无法继续执行代码的原因分析及解决方法

当您在使用电脑过程中遇到提示“缺少d3dx9_42.dll”时,这实际上是操作系统在运行某些应用程序或游戏时遇到的一个常见问题。D3DX9_42.dll是DirectX 9的一部分,DirectX是一组由微软开发的多媒体处理软件组件,广泛用于提升游戏与多媒体程序的性…

【Python项目】高校社团学生会管理系

技术简介:使用Django框架、MYSQL数据库、JS技术、XCode等实现。 系统简介:PYTHON高校社团管理系统的功能需求总体而言可以分为不同的角色,管理员主要包括:社团信息管理、社团活动管理、社团报名管理、留言板、社团会员管理及管理员…

蓝桥杯-网络安全比赛(6) 模拟实验 Metasploit 控制并获取Windows 登录HASH、LM Hash和NTLM Hash密文解析

窃取WINDOWS账号密码 系统环境:主机(Windows系统 IP:192.168.126.129),虚拟机(KALI系统 IP:192.168.126.3),两者需要能通过本地网络互通互连。 攻击工具:Metasploit是一…

随形透气钢是解决模具困气问题的新利器

在制造领域,创新的技术不断推动着行业的发展,3D 打印随形透气钢就是这样一种令人兴奋的创新,它为解决模具困气问题提供了前所未有的便捷。 3D打印随形透气钢,顾名思义就是可以根据工件形状来做透气。很多模具镶件由于位置、形状、…

【计算机毕业设计】基于微信小程序校友会系统的实现

由于APP软件在开发以及运营上面所需成本较高,而用户手机需要安装各种APP软件,因此占用用户过多的手机存储空间,导致用户手机运行缓慢,体验度比较差,进而导致用户会卸载非必要的APP,倒逼 管理者必须改变运营…

SSRF服务器端请求伪造

漏洞原理 SSRF挖掘 SSRF具体利用 SSRF具体验证 SSRF防御与绕过 漏洞原理 这个漏洞允许攻击者去利用服务端的功能,来请求其他网络资源 SSRF(Server-Side Request Forgery:服务器端请求伪造) 是指攻击者能够从易受攻击的 Web应用程序发送精心设计的请求的对其他网站…

Unity基础

概述 基础知识 3D教学 数学计算公共类Mathf 练习: 三角函数 练习: Unity中的坐标系 Vector3向量 向量模长和单位向量 向量加减乘除 练习: 向量点乘 向量叉乘 向量插值运算 Quaternion四元数 为何要使用四元数 四元数是什么 四元数常用方法 四元数计算 练…

优化资源利用,用C++内存池点亮编程之路

内存池介绍(Memory Pool): 它是一种内存分配方式,通过预先分配和复用内存块。 在真正使用内存之前,先申请一大块内存备用。当有新的内存需求时,就从内存池中分出一部分内存块, 若内存块不够再继续申请新的内存。如果我们不需要…