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

Python魔法方法__call__深入详解

目录

1、魔法方法__call__初探 🧙‍♂️

1.1 什么是__call__?

1.2 基础用法演示

1.3 自定义行为与参数传递

2、实现轻量级装饰器模式 🎗️

2.1 装饰器概念回顾

2.2 利用__call__构建装饰器

2.3 深入理解装饰器应用场景

3、类实例变身函数调用 🔮

3.1 类似函数的行为模拟

3.2 动态执行与灵活性提升

3.3 实战案例:日志记录器

4、实现状态机模式 🔄

4.1 状态机概念回顾

4.2 通过__call__管理状态转换

示例代码

4.3 应用实例:简单自动售货机模拟

5、构建轻量级ORM模型 📡

5.1 自定义数据访问对象

示例代码

5.2 实现类的实例直接查询数据库

5.3 链式调用优化查询体验

6、高级用法:元类与__call__结合 🔍

6.1 元类回顾与作用

6.2 通过__call__自定义类实例化过程

6.3 应用实例:类的自动注册系统

6.4 利用元类动态修改__call__

7、性能优化与内存管理 🚀

7.1 __call__与缓存技术

7.2 减少重复实例化开销

7.3 实战分析:性能对比测试

8、总结与展望 🌌



1、魔法方法__call__初探 🧙‍♂️

1.1 什么是__call__?

在Python中,__call__是一个特殊方法,赋予了对象可被直接调用的能力 ,就像函数一样。当一个类实例被当作函数调用时,实际上就是在调用这个类的__call__方法。这为设计灵活、行为动态的对象提供了强大手段,使得对象可以模仿函数行为,实现更高级的面向对象编程模式。

1.2 基础用法演示

下面是一个简单的__call__使用示例,定义了一个Counter类 ,用于计数每次调用的次数:

class Counter:
    def __init__(self):
        self.count = 0    def __call__(self):
        self.count += 1
        return self.count# 创建Counter实例
my_counter = Counter()# 直接调用实例 ,就像调用函数
print(my_counter())  # 输出: 1
print(my_counter())  # 输出: 2

1.3 自定义行为与参数传递

__call__方法不仅限于无参数调用,它还可以接收任意数量的位置参数和关键字参数,从而实现更加复杂的逻辑。比如,创建一个Multiplier类,使其能够接受一个乘数并返回与该乘数相乘的结果:

class Multiplier:
    def __init__(self, factor):
        self.factor = factor    def __call__(self, value):
        return self.factor * value# 使用Multiplier类
times_three = Multiplier(3)# 传递参数调用实例
print(times_three(10))  # 输出: 30

通过这种方式,__call__魔法方法不仅增加了代码的可读性和灵活性 ,还为实现更高级的设计模式 ,如装饰器、策略模式等,奠定了基础。掌握__call__的应用,是深入理解Python面向对象编程的重要一步。

2、实现轻量级装饰器模式 🎗️

2.1 装饰器概念回顾

装饰器是一种特殊类型的函数,可以修改其他函数的功能或行为,而无需更改被修饰函数的源代码。它们在Python中广泛应用于日志记录、性能测试、权限校验等多种场景,极大地增强了代码的可重用性和灵活性。

2.2 利用__call__构建装饰器

利用类的__call__方法可以轻松实现装饰器功能,这种方式让装饰器本身更加模块化和可配置。下面是一个简单的示例,展示如何通过定义一个类作为装饰器来记录函数的执行时间:

import timeclass TimerDecorator:
    def __init__(self, func):
        self.func = func    def __call__(self, *args, **kwargs):
        start_time = time.time()
        result = self.func(*args, **kwargs)
        end_time = time.time()
        print(f"{self.func.__name__} executed in {end_time - start_time:.4f}s")
        return result@TimerDecorator
def example_function():
    time.sleep(1)
    print("Function executed")example_function()

在这个例子中,TimerDecorator类通过__call__方法实现了装饰器逻辑 ,测量并打印了被装饰函数example_function的执行时间。

2.3 深入理解装饰器应用场景

装饰器的使用远不止于此,它在实际开发中扮演着多面手的角色:

  • • 日志记录:自动记录函数调用的日志,包括入参、出参及异常信息 ,便于监控和调试。

  • • 性能测试:评估函数执行效率,如上述时间记录装饰器。

  • • 权限控制:在函数执行前检查用户权限,增强安全性。

  • • 缓存机制:对耗时操作的结果进行缓存,提高程序响应速度。

  • • 参数验证:自动验证函数输入参数的有效性,减少错误处理代码。

通过结合__call__,我们可以创建出更加复杂和灵活的装饰器,为Python程序添加丰富的功能,同时保持代码的整洁和可维护性。

3、类实例变身函数调用 🔮

3.1 类似函数的行为模拟

通过实现__call__方法,类实例可以像普通函数那样直接被调用。这种设计模式允许我们封装复杂的逻辑和状态到类中,同时保持调用接口的简洁。例如,创建一个MathOperation类 ,其行为如同一个加法函数,但内部可以包含更复杂的计算逻辑:

class MathOperation:
    def __init__(self, a, b):
        self.a = a
        self.b = b    def __call__(self):
        return self.a + self.b# 实例化并像函数一样调用
addition = MathOperation(3, 4)
result = addition()  # 输出: 7

3.2 动态执行与灵活性提升

__call__方法的动态特性,使得类可以根据运行时的情况调整行为。这对于需要在调用时刻决定具体执行逻辑的场景非常有用。例如,一个根据用户输入动态选择算法的框架:

class AlgorithmSelector:
    def __init__(self, algorithm_name):
        self.algorithm_name = algorithm_name    def __call__(self, data):
        if self.algorithm_name == 'sort':
            return sorted(data)
        elif self.algorithm_name == 'reverse':
            return data[::-1]
        else:
            raise ValueError("Unsupported algorithm")# 动态选择排序或反转操作
selector = AlgorithmSelector('sort')
sorted_list = selector([3, 1, 4, 1, 5])  # 输出: [1, 1, 3, 4, 5]selector = AlgorithmSelector('reverse')
reversed_list = selector([3, 1, 4, 1, 5])  # 输出: [5, 1, 4, 1, 3]

3.3 实战案例:日志记录器

构建一个简单的日志记录器,利用__call__方法实现不同级别的日志输出,并能够动

相关文章:

Python魔法方法__call__深入详解

目录 1、魔法方法__call__初探 🧙‍♂️ 1.1 什么是__call__? 1.2 基础用法演示 1.3 自定义行为与参数传递 2、实现轻量级装饰器模式 🎗️ 2.1 装饰器概念回顾 2.2 利用__call__构建装饰器 2.3 深入理解装饰器应用场景 3、类实例变身函数调用 🔮 3.1 类似函数的…...

PyQt5 生成py文件不能运行;pushButton点击事件;QTextEdit 获取输入框内容

目录 cant open file c.pyuic: c.pyuic $FileName$ -o $FileNameWithoutExtension$.p PyQt5 生成py文件不能运行 pushButton点击事件 QTextEdit 获取输入框内容 整体运行代码: Creating a Qt Widget Based Application | Qt Creator Manual cant open file c.pyuic: c.…...

HarmonyOS最佳实践文档总结汇总(面试题可能会问)

api12 上面来了最佳实现方案,未来面试题有的问了 编号分类内容子类链接 1性能体验设计体验设计概述 文档中心用户体验设计 文档中心流畅评测指标 文档中心交互流畅体验设计 文档中心视觉流畅体验设计 文档中心2性能优化开发高性能ArkUIUI组件性能优化文档中心合…...

leetcode 56合并区间

思路 合并就是首先应该按照left左边界排序,排完序以后,如果i的左边界小于等于i-1的右边界,说明有重合,此时这两个可以合并,右边界应该取最大值。 代码 排序 我是定义了一个类,存储左右边界,先将数组转化…...

企业微信内嵌H5项目接入聊天功能

产品需求是,在列表中把符合条件的列表接入聊天功能,以下是详细步骤: 1.引入企业微信 <script src"https://res.wx.qq.com/wwopen/js/jsapi/jweixin-1.0.0.js"></script> 2.获取wx签名(必须要) /*** 获取wx签名**/ export function getWxJsApi(data) {r…...

微信小程序 this.setData高级用法(只更改单个数据)

合理使用 setData | 微信开放文档 1、页面 <view class"h-100px"></view> <view>最简单的数据&#xff1a;</view> <button bind:tap"handleAdd" data-type"1">点我加 1&#xff1a; {{text}}</button> &…...

使用npm发布自己的插件包

文章目录 1. 准备工作1.1 拥有一个npm账号1.2 准备你的插件代码1.3 编写package.json文件 2. 本地测试3. 发布到npm3.1 登录npm3.2 发布插件3.3 更新插件 4. 注意事项 在JavaScript和Node.js的生态系统中&#xff0c;npm&#xff08;Node Package Manager&#xff09;是一个非常…...

前端入门篇(五十二)练习6:transition过渡小动画

所以应该先找到第n个li&#xff0c;找到li再找img&#xff0c;li没有找错&#xff0c;底下又各自只有一个img&#xff0c;解决 ul li:nth-child(1) img { } 描述文字从下往上&#xff1a; 一开始描述也在框框下面&#xff0c;当hover时&#xff0c;translateY(0)&#xff0…...

scrapy模块的基础使用

scrapy模块是爬虫工作者最常用的一个模块之一&#xff0c;因它有许多好用的模板&#xff0c;和丰富的中间件&#xff0c;深受欢迎。 一&#xff0c;scrapy的安装 可以通过pypi的指引进行安装 在终端内输入以下代码&#xff1a; pip install scrapy 二&#xff0c;项目的建…...

如何在不降低网络安全防护的前提下,优化pcdn的流量清洗效率?

在不降低网络安全防护的前提下&#xff0c;优化PCDN的流量清洗效率是一个复杂但至关重要的任务。以下是一些建议&#xff0c;帮助您实现这一目标&#xff1a; 一&#xff0e;升级硬件与网络设备&#xff1a; 投资于高性能的硬件和网络设备&#xff0c;以确保流量清洗过程中的…...

linux发行版CentOS、Debian和Ubuntu的对比

一、CentOS、Debian和Ubuntu优缺点比较 CentOS、Debian和Ubuntu是目前国内云服务市场上最常见三个linux发行版本&#xff0c;在我们选购云服务时&#xff0c;要怎么选择&#xff1f;以下表格详细介绍了三者之间的优缺点和适用场景。 特性CentOSDebianUbuntu优点稳定性高&…...

WordPress如何删除内存中的缓存?

今天boke112百科将某篇文章修改分类和内容更新后&#xff0c;发现文章底部的相关文章显示的内容跟文章分类、标签毫无关系&#xff0c;还是显示原来的旧内容。后来查看YIA主题相关文章的代码&#xff0c;才发现相关文章的数据保存到内存中的&#xff0c;而且是永不过期&#xf…...

【XML模版文件参数初始化】

XML 模版文件&#xff0c;内部存在需要自定义的数据&#xff0c;使用 Python 进行初始化。 1、存在一个 XML 模版文件&#xff0c;定义如下 <!-- 文件名称 index.xml --> <root><HEAD><VER>1.0</VER><SRC>10000000000000</SRC><…...

Golang | Leetcode Golang题解之第160题相交链表

题目&#xff1a; 题解&#xff1a; func getIntersectionNode(headA, headB *ListNode) *ListNode {if headA nil || headB nil {return nil}pa, pb : headA, headBfor pa ! pb {if pa nil {pa headB} else {pa pa.Next}if pb nil {pb headA} else {pb pb.Next}}retu…...

基于FOC控制器的BLDC无刷直流电机控制系统matlab编程与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于FOC控制器的BLDC无刷直流电机控制系统matlab编程与仿真&#xff0c;使用MATLAB编程实现&#xff0c;包括FOC控制器&#xff0c;clark&#xff0c;park等&#xff0c;不使用…...

ffmpeg转换视频格式

ffmpeg -i "录屏 2024-06-16 01-56-40.webm" -vf "scale1912:1070" -vcodec libx264 pit.mp4如果你觉得视频压缩速度太慢&#xff0c;可以尝试以下几种方法来加速视频处理&#xff1a; 1. 使用多线程 FFmpeg 支持多线程&#xff0c;可以利用多个 CPU 核心…...

设计程序,利用栈实现数值转换

二、利用栈实现数值转换&#xff0c;先定义一个栈的顺序存储结构&#xff0c;那么我们需要定义一个结构体&#xff0c;结构体里面有个int类型的数组&#xff0c;还有一个top用来存储栈顶元素的下标。栈是一种基本的数据结构&#xff0c;它遵循先进后出的原则。这意味着最后添加…...

QSharedMemory使用详解

QSharedMemory 是 Qt 提供的一个类&#xff0c;用于在多个进程之间共享内存。它可以让您在不同的进程间传递数据&#xff0c;而无需通过文件或网络来进行传输。下面是 QSharedMemory 的详细用法和相关知识点。 一、基本概念 共享内存&#xff1a;共享内存是一块可以被多个进程…...

中电金信:保险业多项举措共绘数字化转型新篇章

...

Gartner发布2024年人工智能技术成熟度曲线:29项决定人工智能领域发展方向的前沿和趋势性技术

人工智能投资已达到新高&#xff0c;重点是生成式人工智能&#xff0c;但在大多数情况下&#xff0c;该技术尚未实现预期的商业价值。这项研究通过分析各种人工智能创新&#xff08;其中许多创新正在快速发展&#xff09;&#xff0c;帮助人工智能领导者确定其他值得投资的技术…...

顺势而为:雷军、小米与创业成功的深层思考

一、引言 在当今快速发展的商业环境中&#xff0c;成功的企业家如马云和雷军&#xff0c;都以其独特的商业智慧和不懈的勤奋精神赢得了业界的尊重。然而&#xff0c;当我们深入探讨他们的成功之道时&#xff0c;会发现一个更为核心的因素——“顺势而为”。本文将基于雷军对不…...

Java+ffmpeg 合并两个mp4文件

使用ffmpeg测试命令 ffmpeg -i "E:\Monitor\video_20240617_10.mp4" -i "E:\Monitor\video1_20240617_10.mp4" -filter_complex "[0:v][0:a][1:v][1:a]concatn2:v1:a1[v][a]" -map "[v]" -map "[a]" -c:v libx264 -c:a…...

汽车IVI中控开发入门及进阶(三十一):视频知识扫盲

有效的视频资源管理需要集成许多不同的底层技术,共同为用户提供给定应用程序的最佳体验。其中许多技术是从早期电视广播中使用的技术演变而来的。其他方法,如用于通过网络流式传输视频的压缩方法,相对较新且不断发展。 以下详细概述了与图形和视频处理和传输相关的一些基本…...

【后端】Java学习笔记(二周目-1)

环境 安装JDK8并配置环境变量 jvm核心类库jre jre开发工具jdk Java基础运行流程&#xff0c;代码从上到下&#xff0c;从左往右&#xff0c;只运行一次 桌面—>新建文件夹—>新建记事本—>打开编写代码 public class Hello{public static void main(String[] arg…...

PDF文档翻译软件哪个好?分享5款快速翻译的工具

世界各地的交流日益密切&#xff0c;文档翻译服务因此变得不可或缺。 无论是企业间的跨国商务合同&#xff0c;还是学术领域的专业研究论文&#xff0c;准确无误地将文档内容翻译成目标语言&#xff0c;对于保障信息的清晰传达和正确理解极为关键。 在这样的背景下&#xff0…...

哪些因素驱动新零售发展?新零售与传统零售、电子商务区别在哪?

零售业正经历着一场前所未有的变革&#xff0c;这场变革由多种因素驱动&#xff0c;涉及技术、消费习惯以及商业模式的全面升级。我们称之为”新零售”&#xff0c;它不仅仅是一个概念&#xff0c;更是零售业未来发展的方向。新零售的兴起&#xff0c;标志着零售行业正在迈向一…...

使用代理IP常见问题及解答

代理IP在互联网数据收集和业务开展中发挥着重要作用&#xff0c;它充当用户客户端和网站服务器之间的“屏障”&#xff0c;可以保护用户的真实IP地址&#xff0c;并允许用户通过不同的IP地址进行操作。然而&#xff0c;在使用代理IP的过程中&#xff0c;用户经常会遇到一些问题…...

重磅!鹅厂大牛带你30分钟玩转AI智能结对编程!

在大模型时代&#xff0c;人工智能技术的突破性进展正重塑着软件开发的面貌。AI的融入不仅优化了代码编写过程&#xff0c;更开启了智能编程的新纪元&#xff0c;为开发者带来了前所未有的工作效率和创新可能。AI结对编程不仅能够极大提升研发效率&#xff0c;还能通过智能分析…...

研究Redis源码的一些前期准备

一 背景 Redis数据结构讲完后&#xff0c;觉得还是有点不过瘾&#xff0c;想研究一下Redis的底层实现。找了一些相关资料&#xff0c;准备借鉴和学习其他各位大佬钻研Redis底层的方法和经验&#xff0c;掌握Redis实现的基本原理。 二 源码归类 网上有大佬已经总结了…...

用PHP来调用API给自己定制一个“每日新闻”

头条新闻汇聚了互联网上的时事动态&#xff0c;提供最新新闻动态、网络热门话题和视频更新等&#xff0c;覆盖社会、政治、体育、经济、娱乐、科技等多个领域&#xff0c;并不断刷新内容。企业应用这一接口后&#xff0c;可以快速吸引更多的用户访问自己的平台。即使是非新闻类…...

java web做网站/网店推广的作用是

网上有很多使用AS3画一个扇形的方法&#xff0c;但是却一个都没有解释这个函数是如何运作来画出扇形的&#xff0c;下面浅谈下我对这个函数的理解。 首先上代码&#xff0c;代码来自http://blog.csdn.net/weiming8517/article/details/12023411。 private function drawSector(…...

东营企业网站制作/网络服务器多少钱一台

问题描述;研发同事反应MySQL数据库有锁&#xff0c;检查innodb_trx时&#xff0c;发现有很多长时间未结束的空事务。这些事务的trx_mysql_thread_id都为0&#xff0c;因此不能通过kill id 的方式强制关闭这些长时间未结束的僵尸事务。SELECTtrx_mysql_thread_id, trx_id, trx…...

西安装修公司网站制作/免费友情链接交换平台

在实际的开发项目中&#xff0c;监听 key 的过期事件&#xff0c;应用非常广泛&#xff0c;例如&#xff1a;订单超时未支付&#xff0c;优惠券过期等等 一、说明 本篇文章是继&#xff1a; 【SpringBoot】三十四、SpringBoot整合Redis实现序列化存储Java对象 其中涉及到的知…...

江阴网站开发/营销方案设计思路

在这篇博文中&#xff0c;我想详细介绍一下 java.lang.OutOfMemoryError 错误这个错误是如何在Java应用程序中发生的。在前面的条目中&#xff0c;我们看到 **OutOfMemoryError **有完全不同的类型。然而&#xff0c;最常见的错误是Exception in thread "main": java…...

淘宝直播要先建设个网站吗/黑马培训机构可靠吗

Prefacio 平静的生活下暗流涌动&#xff0c;明明每天浪费半天的时间&#xff0c;为什么没有急迫感。不但没有急迫感&#xff0c;也没有普通到让人以为是做梦的感觉&#xff0c;我到底该怎么办。 CatlogoPrefacioNmero0-910-1920-2930/40/50/60/70/80/90/10030以上100以下的非整…...

罗湖网站建设哪家好/百度下载安装2019

我记得大约在半年前&#xff0c;有个朋友问我一个问题&#xff0c;现在有一个选型&#xff1a;一个性能敏感场景&#xff0c;有一个集合&#xff0c;需要确定某一个元素在不在这个集合中&#xff0c;我是用数组直接Contains还是使用HashSet<T>.Contains&#xff1f;大家肯…...