python面向对象中__new__和__init__区别

 更新时间:2026年04月05日 08:55:49   作者:开发者冷雨  
在 Python 的面向对象编程中,__new__ 和 __init__ ,它们的职责、执行顺序和返回值完全不同,下面就来详细的介绍一下两者的区别,感兴趣的可以了解下

在 Python 的面向对象编程中,__new__ 和 __init__ ,它们的职责、执行顺序和返回值完全不同。

__new__ 负责“出生”(创建实例),__init__ 负责“成长”(初始化属性)。

1. 核心区别对比表

特性__new____init__
本质静态方法(不需要 self )实例方法
执行时机最先执行,在实例创建之前随后执行,在实例创建之后
主要职责创建并返回一个新的实例对象初始化已经创建的实例对象(赋值属性)
第一个参数cls (类本身)self (刚刚创建好的实例)
返回值必须返回一个实例对象 (通常由 super().__new__(cls) 返回)不需要返回值 (默认返回 None,若返回其他值会报错)
使用场景继承不可变类型、单例模式、控制实例创建过程绝大多数常规的属性初始化

2. 执行流程详解

当你调用 MyClass() 时,Python 内部实际上做了以下步骤:

  1. 调用 __new__ 方法:
    • 传入类 cls。
    • 内存中分配空间,创建一个空的对象。
    • 返回这个新对象。
  2. 如果 __new__ 返回的是该类的实例,Python 会自动调用 __init__ 方法:
    • 将 __new__ 返回的对象作为 self 传入。
    • 执行初始化代码(如 self.name = ...)。
    • __init__ 执行完毕,对象完全准备好。

3. 代码示例

场景 A:常规用法(只看init)

99% 的情况下,你只需要写 __init__,因为 __new__ 默认由 object 类处理好了。

class Person:
    def __init__(self, name):
        print(f"2. __init__ 被调用,正在初始化: {name}")
        self.name = name

p = Person("Alice")
# 输出:
# 2. __init__ 被调用,正在初始化: Alice

场景 B:同时展示两者(看执行顺序)

class Demo:
    def __new__(cls, *args, **kwargs):
        print("1. __new__ 被调用:负责创建实例")
        # 必须调用父类的 __new__ 来真正创建对象,否则 __init__ 不会执行
        instance = super().__new__(cls)
        return instance

    def __init__(self, value):
        print("2. __init__ 被调用:负责初始化属性")
        self.value = value

obj = Demo(100)
print(f"最终对象值: {obj.value}")

输出结果:

1. __new__ 被调用:负责创建实例
2. __init__ 被调用:负责初始化属性
最终对象值: 100

4. 什么时候必须使用__new__?

既然 __init__ 这么好用,为什么还需要 __new__?主要在以下三种高级场景:

① 继承不可变类型(如int,str,tuple)

不可变类型一旦创建就不能修改。__init__ 是在对象创建后才运行的,此时对象已经定型,无法修改其值。必须在创建时(__new__)就确定值。

class MyInt(int):
    # 想要强制让生成的整数都是偶数
    def __new__(cls, value):
        # 在创建之前就修改值
        if value % 2 != 0:
            value += 1
        return super().__new__(cls, value)
    
    # __init__ 在这里无法修改整数的值,因为 int 是不可变的

num = MyInt(5)
print(num)  # 输出 6 (自动变成了偶数)

② 实现单例模式 (Singleton)

确保一个类只有一个实例。可以在 __new__ 中判断实例是否已存在,如果存在则直接返回旧的,不再创建新的。

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            print("创建新实例")
            cls._instance = super().__new__(cls)
        else:
            print("返回已有实例")
        return cls._instance

    def __init__(self, name):
        # 注意:即使返回旧实例,__init__ 仍会被调用,通常需要小心处理
        self.name = name

s1 = Singleton("A")
s2 = Singleton("B")

print(s1 is s2)  # True (是同一个对象)
print(s2.name)   # "B" (注意:__init__ 再次运行覆盖了名字)

③ 控制实例的创建过程

比如根据参数决定返回哪个类的实例(工厂模式的一种变体),或者限制只能创建特定数量的实例。

class Shape:
    def __new__(cls, shape_type, *args, **kwargs):
        if shape_type == "circle":
            return super().__new__(Circle)
        elif shape_type == "square":
            return super().__new__(Square)
        return super().__new__(cls)

class Circle(Shape):
    pass

class Square(Shape):
    pass

c = Shape("circle")
print(type(c))  # <class '__main__.Circle'>

总结

  • 日常开发:只用 __init__。
  • 需要修改不可变对象、控制实例生成(单例)、或动态返回不同子类实例时:使用 __new__。
  • 记住:__new__ 是造物主(返回实例),__init__ 是装修工(修饰实例)。如果没有造物主造出房子,装修工是无活可干的。

到此这篇关于python面向对象中__new__和__init__区别的文章就介绍到这了,更多相关python __new__和__init__区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python用栈实现队列的基本操作

    Python用栈实现队列的基本操作

    队列(Queue)和栈(Stack)是常见的数据结构,它们在计算机科学中有着广泛的应用,在Python中,可以使用列表(List)来实现栈,但要用栈来实现队列需要一些巧妙的操作,本文就给大家详细介绍一下Python中如何用栈实现队列,需要的朋友可以参考下
    2023-11-11
  • python的pip配置的国内镜像的实现

    python的pip配置的国内镜像的实现

    本文主要介绍了python的pip配置的国内镜像的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-05-05
  • Python Pandas条件筛选功能

    Python Pandas条件筛选功能

    这篇文章主要介绍了Python Pandas条件筛选功能,筛选是在平时的工作中使用非常频繁的功能了,下文详细的相关资料介绍,需要的小伙伴可以参考一下
    2022-03-03
  • 用python制作个视频下载器

    用python制作个视频下载器

    这篇文章主要介绍了如何用python制作个视频下载器,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下
    2021-02-02
  • Python类中使用cursor.execute()时语法错误的解决方法

    Python类中使用cursor.execute()时语法错误的解决方法

    在 Python 类中使用 cursor.execute() 时,出现语法错误(如 SyntaxError 或 SQL 语法相关错误)通常是因为 SQL 语句格式不正确、占位符使用不当,或参数传递方式不符合预期,以下是解决此类问题的常见方法和建议,需要的朋友可以参考下
    2024-09-09
  • Pytorch转tflite方式

    Pytorch转tflite方式

    这篇文章主要介绍了Pytorch转tflite方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-05-05
  • tensorflow指定CPU与GPU运算的方法实现

    tensorflow指定CPU与GPU运算的方法实现

    这篇文章主要介绍了tensorflow指定CPU与GPU运算的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-04-04
  • python中flatten()函数用法详解

    python中flatten()函数用法详解

    本文主要介绍了python中flatten()函数用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • Python中的错误和异常处理简单操作示例【try-except用法】

    Python中的错误和异常处理简单操作示例【try-except用法】

    这篇文章主要介绍了Python中的错误和异常处理简单操作,结合实例形式分析了Python中try except在错误与异常处理中的用法,需要的朋友可以参考下
    2017-07-07
  • 关于PySnooper 永远不要使用print进行调试的问题

    关于PySnooper 永远不要使用print进行调试的问题

    这篇文章主要介绍了关于PySnooper 永远不要使用print进行调试的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03

最新评论