news 2026/6/14 20:57:06

Python 高手编程系列三千四百二十:使用 __new __()方法覆写实例创建过程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 高手编程系列三千四百二十:使用 __new __()方法覆写实例创建过程

特殊方法__new__()是一种负责创建类实例的静态方法。它很特殊,所以无需使用
staticmethod 装饰器将其声明为静态方法。new(cls, [,…])方法的调用优先
于__init__()初始化方法。通常来说,覆写__new__()的实现将会使用合适的参数调用其
超类的 super().new(),并在返回之前修改实例:
class InstanceCountingClass:
instances_created = 0
defnew(cls, *args, **kwargs):
print(‘new() called with:’, cls, args, kwargs)
instance = super().new(cls)
instance.number = cls.instances_created
cls.instances_created += 1
return instance
definit(self, attribute):
print(‘init() called with:’, self, attribute)
self.attribute = attribute
下面是在交互式会话中的日志示例,展示了 InstanceCountingClass 实现的工作
方式:

instance1 = InstanceCountingClass(‘abc’)
__new __() called with: <class ’ __main __.InstanceCountingClass’> (‘abc’,)
{}
__init __() called with: < __main __.InstanceCountingClass object at
0x101259e10> abc
instance2 = InstanceCountingClass(‘xyz’)
__new __() called with: <class ’ __main __.InstanceCountingClass’> (‘xyz’,)
{}
__init __() called with: < __main.InstanceCountingClass object at
0x101259dd8> xyz
instance1.number, instance1.instances
created
(0, 2)
instance2.number, instance2.instances
created
(1, 2)
通常来说,new()方法应该返回该类的一个实例,但也可能返回其他类的实例。
如果发生了这种情况(即返回了其他类的实例),那么将会跳过对__init
()方法的调用。
如果需要修改不可变类实例(例如 Python 的某些内置类型)的创建行为,那么这一点是很
有用的,如下所示:
class NonZero(int):
defnew(cls, value):
return super().new(cls, value) if value != 0 else None
definit(self, skipped_value):

在这个例子中可以跳过__init__的实现

但放在这里是为了展示它如何不被调用

print(“init() called”)
super().init()
我们在交互式会话中查看运行结果如下:

type(NonZero(-12))
__init() called
<class ’main.NonZero’>
type(NonZero(0))
<class ‘NoneType’>
NonZero(-3.123)
init() called
-3
那么什么情况下使用__new
()呢?答案很简单:只有在__init
()不够用的时候。
前面已经提到了这样的一个例子,就是对 Python 不可变的内置类型(如 int、str、float、frozenset 等)进行子类化。这是因为一旦创建了这样不可变的对象实例,就无法在
init()方法中对其进行修改。
有些程序员可能会认为,new()对执行重要的对象初始化可能很有用,如果用户
忘记使用 super(),可能会漏掉这一初始化。init()调用是覆写的初始化方法。虽
然这听上去很合理,但却有一个主要的缺点。如果使用这样的方法,那么即使初始化过程
已经是预期的行为,程序员明确跳过初始化步骤也会变得更加困难。它还破坏一条潜规则,
即在__init
()中执行所有的初始化工作。
由于__new
()不限于返回同一个类的实例,所以很容易被滥用。不负责任地使用这
种方法,可能会对代码有害,因此始终应该谨慎使用,并且提供大量文档来支持。一般来
说,对于特定问题,最好搜索其他可用的解决方法,而不要影响对象创建过程,使其违背
基础程序员的预期。即使是上文提到的覆写不可变类型的初始化的例子,也可以用可预测
性更高且更加完善的设计模式来替代,例如第 14 章介绍的工厂方法。
在 Python 编程中,至少在一个方面大量使用__new
()方法是非常合理的。那就是下
一节将介绍的元类。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/14 20:54:07

3步搞定浏览器资源下载:猫抓Cat-Catch让网络资源秒变本地文件

3步搞定浏览器资源下载&#xff1a;猫抓Cat-Catch让网络资源秒变本地文件 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 你是否曾遇到过这样的场景…

作者头像 李华
网站建设 2026/6/14 20:50:52

Sunshine游戏串流终极指南:5步搭建高性能个人云游戏平台

Sunshine游戏串流终极指南&#xff1a;5步搭建高性能个人云游戏平台 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine Sunshine游戏串流技术为您提供了一个完整的自托管游戏串流解决…

作者头像 李华
网站建设 2026/6/14 20:50:01

MyBatis 入门到项目实战 MyBatis 分页插件 65-66

MyBatis 入门到项目实战 MyBatis 分页插件 65-66 一、参考资料 【MyBatis零基础教程&#xff0c;mybatis快速上手&#xff0c;mybatis入门到项目实战】 https://www.bilibili.com/video/BV1VP4y1c7j7/?p65&share_sourcecopy_web&vd_source855891859b2dc554eace9de3f28…

作者头像 李华
网站建设 2026/6/14 20:35:11

3分钟快速上手猫抓:浏览器资源嗅探的终极解决方案

3分钟快速上手猫抓&#xff1a;浏览器资源嗅探的终极解决方案 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 你是否经常遇到想保存网页中的视频、…

作者头像 李华
网站建设 2026/6/14 20:33:53

MPC8280并行I/O端口配置详解:从寄存器原理到嵌入式工程实践

1. MPC8280并行I/O端口架构深度解析在嵌入式系统开发&#xff0c;尤其是通信处理器领域&#xff0c;I/O引脚的灵活配置能力直接决定了硬件设计的成败。MPC8280 PowerQUICC II作为一款经典的集成通信处理器&#xff0c;其并行I/O端口的设计堪称教科书级别的典范。它不是简单的GP…

作者头像 李华
网站建设 2026/6/14 20:32:53

082、文档自动生成:从代码到 README、API 文档、变更日志的 AI 辅助生成

082、文档自动生成:从代码到 README、API 文档、变更日志的 AI 辅助生成 上周五凌晨两点,我盯着屏幕上一段刚写完的 gRPC 服务端代码,突然意识到一个问题:明天要给新同事交接,但 README 还是三个月前的占位符,API 文档压根没写,变更日志停留在“修复若干 bug”。这不是第…

作者头像 李华