系统学习Python——装饰器:函数装饰器-[对方法进行装饰:基础知识]

分类目录:《系统学习Python》总目录


我们在前面的文章中编写了第一个基于类的tracer函数装饰器的时候,我们简单地假设它也应该适用于任何方法一一一被装饰的方法应该同样地工作,并且自带的self实例参数应该直接包含在*args的前面。但这一假设唯一的实际缺点就是它彻头彻尾地错了!当应用于类方法的时候,tracer的第一个版本失效了,因为self是装饰器类的实例,并且被装饰的主体类的实例没有包含在*args中。在python3.X和Python2.X中都是如此。

现在,我们可以在实际工作代码的上下文中看到这点。假设基于类的跟踪装饰器如下:

class tracer:def __init__(self, func):self.calls = 0self.func = funcdef __call(self, *args, **kwargs):self.calls += 1print('call %s to %s' % (self.calls, self.func.__name__))return self.func(*args, **kwargs)@tracer
def spam(a, b, c):print(a + b + c)

我们可以得到如下输出:
输出结果
然而,类级别方法的装饰失效了:

class Person:def __init__(self, name, pay):self.name = nameself.pay = pay@tracerdef giveRaise(self, percent):self.pay *= (1.0 + percent)@tracerdef lastName(self):return self.name.split()[-1]

我们可以得到如下输出:
输出结果
这里问题的根源在于tracer类的__call__方法的self参数是一个tracer实例,还是一个Person实例?其实我们两者都需要:tracer用于记录装饰器状态,Person用于指向最初的方法。实际上,self必须是tracer对象,以提供对tracer的状态信息(它的callsfunc)的访问;不管装饰一个简单函数还是装饰一个方法,都是如此。

遗憾的是,当我们用__call__把被装饰方法名称重绑定到一个类实例对象的时候,Python只向self传递了tracer实例;它根本没有在参数列表中传递Person主体。此外,由于tracer不知道我们要利用方法调用处理的Person`实例的任何信息,因此没有办法创建一个带有实例的绑定方法,也没有办法正确地分发调用。这不是一个漏洞,但却是一个非常值得注意的细节。

最后,前面的列表最终传递了太少的参数给被装饰的方法,并且导致了一个错误。在装饰器的__call__方法添加一行,以打印所有的参数来验证这一点一一正如我们所看到的,self是一个tracer实例,而Person实例则完全缺失:
输出结果
正如前面提到的,出现这种情况是因为仅当一个方法名绑定到一个简单函数时,Python才向self传递隐含的主体实例;当它是可调用类的实例时,就向self传递这个类的实例。从技术上讲,仅当方法是一个简单函数,而不是另一个类的可调用实例的时候,Python才会创建一个绑定的方法对象,其中包含了主体实例。

参考文献:
[1] Mark Lutz. Python学习手册[M]. 机械工业出版社, 2018.

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

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

相关文章

7-2 换硬币

将一笔零钱换成5分、2分和1分的硬币,要求每种硬币至少有一枚,有几种不同的换法? 输入格式: 输入在一行中给出待换的零钱数额x∈(8,100)。 输出格式: 要求按5分、2分和1分硬币的数量依次从大到小的顺序,输出各种换法。每行输出…

计算机基础面试题 |04.精选计算机基础面试题

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

python打开文件的方式比较

open(addr,w) 打开之后文件无论以前有什么,打开后都要清空 /// open(addr,r) 文件打开后,不删除以前内容

Ubuntu连接xshell

安装ssh服务器 sudo apt-get install openssh-server​ 重启ssh sudo service ssh restart 3.启动ssh服务 /etc/init.d/ssh start4.修改文件,允许远程登陆 sudo vi /etc/ssh/sshd_config PermitRootLogin prohibit-password #默认为禁止登录 PermitRootLogin y…

JAVA Web 期末复习

期末复习 填空题简答题:一、数据库连接池的工作机制是什么:二、javabean的规范:三、POST和GET请求的区别四、请求转发和重定向的区别五、简述pageContext的作用:六、什么是重定向七、简述一下MVC及作用八、cookie和session九、简述…

多人协同开发git flow,创建初始化项目版本

文章目录 多人协同开发git flow,创建初始化项目版本1.gitee创建组织模拟多人协同开发2.git tag 打标签3.git push origin --tags 多人协同开发git flow,创建初始化项目版本 1.gitee创建组织模拟多人协同开发 组织中新建仓库 推送代码到我们组织的仓库 2…

国家开放大学形成性考核 统一考试 资料参考

试卷代号:11130 卫生法学 参考试题(开卷) 一、单选题(每题2分,共30分) 1.省、自治区、直辖市及省会所在地的市人大及其常委会,或经国务院批准的较大的市的人大及其常委会,依法…

STM32与TB6612电机驱动器的基础入门教程

TB6612是一款常用的双路直流电机驱动芯片,适用于小型机器人以及其他需要控制电机方向和转速的应用。在STM32微控制器的配合下,可以实现对TB6612电机驱动器的控制,进而实现电机的控制。本文将带领读者一步步了解如何搭建基于STM32与TB6612的电…

Python基础-03(算数运算符、赋值运算符)

文章目录 前言一、算数运算符二、赋值运算符()1.赋值运算符()2.复合赋值运算符 总结 前言 两种非常基础的运算符,看一下就懂,不需要过多的去深究细节 一、算数运算符 稍微着重看下 除法/ (不要…

我从来不理解JavaScript闭包,但我用了它好多年

前言 📫 大家好,我是南木元元,热衷分享有趣实用的文章,希望大家多多支持,一起进步! 🍅 个人主页:南木元元 你是否学习了很久JavaScript但还没有搞懂闭包呢?今天就来聊一下…

SpringBoot解决前后端分离跨域问题:状态码403拒绝访问

最近在写和同学一起做一个前后端分离的项目,今日开始对接口准备进行 登录注册 的时候发现前端在发起请求后,抓包发现后端返回了一个403的错误,解决了很久发现是【跨域问题】,第一次遇到,便作此记录✍ 异常描述 在后端…

Java---网络编程

文章目录 1. 网络编程概述2. InetAddress3. 端口和协议4. Java网络API5. URL6. URLConnection类 1. 网络编程概述 1. 计算机网络:是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统、网络管理软…

2024年Mac专用投屏工具AirServer 7 .27 for Mac中文版

AirServer 7 .27 for Mac中文免费激活版是一款Mac专用投屏工具,能够通过本地网络将音频、照片、视频以及支持AirPlay功能的第三方App,从 iOS 设备无线传送到 Mac 电脑的屏幕上,把Mac变成一个AirPlay终端的实用工具。 目前最新的AirServer 7.2…

Matlab技巧[绘画逻辑分析仪产生的数据]

绘画逻辑分析仪产生的数据 逻分上抓到了ADC数字信号,一共是10Bit,12MHZ的波形: 这里用并口协议已经解析出数据: 导出csv表格数据(这个数据为补码,所以要做数据转换): 现在要把这个数据绘制成波形,用Python和表格直接绘制速度太慢了,转了一圈发现MATLAB很好用,操作方法如下:…

Bag-of-Words(BoW)

Bag-of-Words(BoW)模型是一种用于自然语言处理(NLP)的基本文本表示方法。它的核心思想是将文本数据转化为一个"词袋",忽略文本中词语的顺序和语法,只关注词汇的出现与否。BoW模型通常包括以下步骤…

逗号表达式与赋值表达式

逗号表达式和赋值表达式是C语言中常用的表达式类型。它们可以用于各种目的,包括计算和评估表达式、初始化变量、为函数调用提供参数以及将值分配给变量。 逗号表达式 逗号表达式允许在单个语句中计算和评估多个表达式。逗号分隔每个表达式,并且表达式从…

力扣134. 加油站

迭代 思路: 暴力模拟迭代;假设从第 idx 个加油站开始,使用一个变量对行驶的加油站个数计数,如果最后行驶的个数为 size,则是可行的;否则,行驶过的加油站都不可行;(加快更…

TypeScript 的基础语法

书接上上文:关于vue3的知识点 和 上文 :TypeScript的安装与报错 我们来接着看TypeScript 的基础语法 TypeScript 语法 1. 类型注解 类型注解是 变量后面约定类型的语法,用来约定类型,明确提示 // 约定变量 age 的类型为 numbe…

Ubuntu Linux 入门指南:面向初学者

目录 1. Ubuntu Linux 简介 Ubuntu 的由来 Ubuntu 与其他 Linux 发行版的比较 Debian: Fedora: openSUSE: Arch Linux: Linux Mint: 第二部分:安装 Ubuntu 1. 准备安装 系统需求 创建 Ubuntu 启…

Spring Cloud Gateway + Nacos 灰度发布

前言 本文将会使用 SpringCloud Gateway 网关组件配合 Nacos 实现灰度发布&#xff08;金丝雀发布&#xff09; 环境搭建 创建子模块服务提供者 provider&#xff0c;网关模块 gateway 父项目 pom.xml 配置 <?xml version"1.0" encoding"UTF-8"?…