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

Python __new__ 一个特殊的静态方法

Python __new__ 一个特殊的静态方法

flyfish

在 Python 中,__new__ 是一个特殊的静态方法,主要用于创建并返回一个新的对象实例。它是对象实例化过程中调用的第一个方法,先于 __init__ 方法执行。

基本语法

__new__ 方法的基本语法如下:

class ClassName:def __new__(cls, *args, **kwargs):# 创建并返回对象实例return super().__new__(cls)

这里的 cls 代表类本身,类似于 self 代表实例本身。*args**kwargs 用于接收传递给类构造函数的参数。

执行顺序

在创建类的实例时,Python 解释器会先调用 __new__ 方法来创建对象,接着才会调用 __init__ 方法对这个对象进行初始化。下面是一个简单示例:

class MyClass:def __new__(cls, *args, **kwargs):print("__new__ 方法被调用")instance = super().__new__(cls)return instancedef __init__(self):print("__init__ 方法被调用")obj = MyClass()

创建 MyClass 的实例 obj 时,__new__ 方法会首先被调用,创建对象实例,然后 __init__ 方法会对这个实例进行初始化。

  • __new__ 方法必须返回一个对象实例,不然 __init__ 方法将不会被调用。
  • 由于 __new__ 是静态方法,所以在定义时要使用 cls 作为第一个参数。

__new____init__ 方法中使用 *args**kwargs 参数

*args 用于接收任意数量的位置参数,而 **kwargs 用于接收任意数量的关键字参数

示例 1:在 __init__ 方法中使用参数

class MyClass:def __new__(cls, *args, **kwargs):print("__new__ 方法被调用")instance = super().__new__(cls)return instancedef __init__(self, name, age):print("__init__ 方法被调用")self.name = nameself.age = ageprint(f"姓名: {self.name}, 年龄: {self.age}")obj = MyClass("Alice", age=25)

在这个例子中,__new__ 方法未对 *args**kwargs 进行处理,只是创建了一个实例。而在 __init__ 方法中,我们接收了两个参数 nameage,并将它们赋值给实例的属性。

示例 2:在 __new__ 方法中根据参数创建不同类型的实例

class Rectangle:def __init__(self, width, height):self.width = widthself.height = heightprint(f"创建了一个矩形,宽: {self.width}, 高: {self.height}")class Square:def __init__(self, side):self.side = sideprint(f"创建了一个正方形,边长: {self.side}")class ShapeFactory:def __new__(cls, *args, **kwargs):print("__new__ 方法被调用")if len(args) == 1 or 'side' in kwargs:side = args[0] if args else kwargs['side']return Square(side)elif len(args) == 2 or ('width' in kwargs and 'height' in kwargs):width = args[0] if args else kwargs['width']height = args[1] if len(args) > 1 else kwargs['height']return Rectangle(width, height)else:return super().__new__(cls)def __init__(self, *args, **kwargs):print("__init__ 方法被调用")# 创建正方形
square = ShapeFactory(side=5)
# 创建矩形
rectangle = ShapeFactory(3, 4)

ShapeFactory 类的 __new__ 方法会依据传入的参数来决定创建 Square 还是 Rectangle 类的实例。如果传入一个参数或者包含 side 关键字参数,就创建 Square 实例;如果传入两个参数或者包含 widthheight 关键字参数,就创建 Rectangle 实例。

常见的使用场景

__new__ 方法是 Python 中对象实例化时调用的第一个方法,通常情况下使用默认的对象创建机制即可

1. 实现单例模式

单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。通过重写 __new__ 方法,可以控制类实例的创建过程,保证只有一个实例被创建。

class Singleton:_instance = Nonedef __new__(cls, *args, **kwargs):if not cls._instance:cls._instance = super().__new__(cls)return cls._instances1 = Singleton()
s2 = Singleton()
print(s1 is s2)  # 输出 True,说明 s1 和 s2 是同一个实例

2. 自定义对象创建逻辑

当需要根据不同的条件创建不同类型的对象时,可以在 __new__ 方法中实现自定义的对象创建逻辑。

class Rectangle:def __init__(self, width, height):self.width = widthself.height = heightclass Square:def __init__(self, side):self.side = sideclass ShapeFactory:def __new__(cls, width, height):if width == height:return Square(width)else:return Rectangle(width, height)shape1 = ShapeFactory(2, 2)
shape2 = ShapeFactory(3, 4)
print(type(shape1))  # 输出 <class '__main__.Square'>
print(type(shape2))  # 输出 <class '__main__.Rectangle'>

3. 实现不可变对象的子类

对于不可变对象(如 intstrtuple 等),在创建子类时,可能需要在对象创建时进行一些额外的处理。由于不可变对象一旦创建就不能修改,因此需要在 __new__ 方法中完成这些处理。

class CustomInt(int):def __new__(cls, value):if value < 0:value = 0return super().__new__(cls, value)num = CustomInt(-5)
print(num)  # 输出 0

4. 元类编程

在元类编程中,__new__ 方法用于控制类的创建过程。元类是创建类的类,通过重写元类的 __new__ 方法,可以在类创建时进行一些额外的操作,如修改类的属性、方法等。

class MyMeta(type):def __new__(cls, name, bases, attrs):# 在类创建时添加一个新的属性attrs['new_attribute'] = 'This is a new attribute'return super().__new__(cls, name, bases, attrs)class MyClass(metaclass=MyMeta):passprint(MyClass.new_attribute)  # 输出 'This is a new attribute'

5. 缓存对象

如果你希望对某些对象进行缓存,避免重复创建相同的对象,可以在 __new__ 方法中实现缓存逻辑。

class CachedObject:_cache = {}def __new__(cls, key):if key not in cls._cache:cls._cache[key] = super().__new__(cls)return cls._cache[key]obj1 = CachedObject('key1')
obj2 = CachedObject('key1')
print(obj1 is obj2)  # 输出 True,说明 obj1 和 obj2 是同一个对象

特殊的静态方法

__new__ 被视为特殊的静态方法,主要是因为它虽然未使用 @staticmethod 装饰器,却具备静态方法的一些关键特性,同时还有自身独特之处

具备静态方法特性

无需实例调用

和普通的静态方法一样,__new__ 不需要通过类的实例来调用,而是在创建类的实例时由 Python 解释器自动调用。在对象实例化过程中,Python 解释器会直接调用类的 __new__ 方法来创建对象,无需先创建实例再调用方法。

不依赖实例状态

静态方法不依赖于类的实例状态,__new__ 同样如此。__new__ 方法的第一个参数 cls 代表类本身,而不是类的实例,它在创建对象时不会访问或修改特定实例的属性,其主要作用是创建并返回一个新的对象实例。

自身独特之处

自动调用机制

__new__ 方法在对象实例化时会被 Python 解释器自动调用,且先于 __init__ 方法执行。这是普通静态方法所没有的特性,普通静态方法需要显式调用。

必须返回实例

__new__ 方法有一个严格的要求,就是必须返回一个对象实例。如果 __new__ 方法没有返回实例,那么 __init__ 方法将不会被调用,因为 __init__ 方法是用于对 __new__ 方法创建的实例进行初始化的。

下面通过代码示例来展示 __new__ 方法的调用过程:

class MyClass:def __new__(cls, *args, **kwargs):print("__new__ 方法被调用")instance = super().__new__(cls)return instancedef __init__(self):print("__init__ 方法被调用")obj = MyClass()

在这个例子中,当创建 MyClass 的实例 obj 时,Python 解释器会自动调用 __new__ 方法创建对象,然后再调用 __init__ 方法对该对象进行初始化。
__new__ 虽然没有使用 @staticmethod 装饰器,但它具备静态方法的一些核心特性,同时又有自身独特的调用机制和返回要求,因此被称为特殊的静态方法。

相关文章:

  • 使用Windows+Linux实现mysql的主从复制
  • LangChain入门(六)Agent
  • day5:nginx代理-动静分离
  • 【了解】通感算一体化网络
  • Selenium模拟人类行为,操作网页的方法(全)
  • 每日算法-250506
  • 大模型系列(三)--- ​ GPT1: Improving Language Understanding by Generative Pre-Training​
  • 【HarmonyOS 5】鸿蒙用户头像编辑功能实践
  • 基于【抖音弹幕抓取数据推送】——制作抖音消息分类查看界面
  • YOLOv8的Python基础--函数篇
  • B站pwn教程笔记-6
  • Linux[Makefile]
  • Vue3路由模式为history,使用nginx部署上线后刷新404的问题
  • Leetcode - 周赛448
  • PostgreSQL数据库的array类型
  • 密码工具类-生成随机密码校验密码强度是否满足要求
  • GPS定位方案
  • 使用阿里AI的API接口实现图片内容提取功能
  • three.js通过GEO数据生成3D地图
  • 2025年5月HCIP题库(带解析)
  • 视频丨习近平主席出席俄方在机场举行的迎宾仪式
  • 百济首次实现季度营业利润扭亏,泽布替尼销售额近57亿元
  • 安徽六安原市长潘东旭,已任省市场监督管理局党组书记、局长
  • 央行:增加支农支小再贷款额度3000亿元
  • 央行:5月8日起,下调个人住房公积金贷款利率0.25个百分点
  • 人民日报评论:莫让“胖东来们”陷入“棒杀”“捧杀”泥潭