卡码笔记-最强八股文
首页
计算机基础
Python
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
大模型Github (opens new window)
代码随想录 (opens new window)
首页
计算机基础
Python
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
大模型Github (opens new window)
代码随想录 (opens new window)
  • 本栏必读

    • Python面试题专栏介绍
    • Python学习路线
    • Python零基础入门课
  • 基础语法

  • 函数、作用域与模块

  • 面向对象

    • Python中的类和对象是什么?
    • 实例属性和类属性有什么区别?
    • 实例方法、类方法和静态方法有什么区别?
    • __new__和__init__有什么区别?
      • 简要回答
      • 详细回答
      • 知识拓展
    • Python如何实现封装、继承和多态?
    • Python多继承的MRO是什么?super()如何工作?
    • Python常见魔术方法有哪些?
  • 进阶语法与语言机制

# __new__和__init__有什么区别?

面试官问:"Python的__new__和__init__有什么区别?"

很多人只知道__init__是初始化方法,不知道还有__new__。真正要讲清楚的是:__new__负责创建对象并返回它,__init__负责初始化已经创建好的对象。 __new__先执行,返回值是对象本身;__init__后执行,在对象上添加属性,没有返回值。单例模式和自定义不可变类型时会重写__new__。

# 简要回答

__new__是类方法,负责创建对象。 它的第一个参数是cls(类本身),返回一个新创建的对象。如果__new__返回的是这个类的实例,Python会自动调用__init__初始化它。

__init__是实例方法,负责初始化对象。 它的第一个参数是self(刚创建好的对象),用于设置对象的初始属性。__init__不需要返回值,返回None。

调用顺序:obj = Class(args) → __new__(cls, args) → 返回对象 → __init__(self, args) → 返回给调用方。

# 详细回答

# 调用过程

当你写obj = MyClass(a, b)时,Python实际执行:

  1. 调用MyClass.__new__(MyClass, a, b),创建对象。
  2. 如果__new__返回的是MyClass的实例,**调用obj.__init__(a, b)**初始化。
  3. 返回初始化后的对象。
class Person:
    def __new__(cls, name):
        print(f"__new__ called with cls={cls}, name={name}")
        instance = super().__new__(cls)  # 调用object.__new__创建对象
        print(f"__new__ returns {instance}")
        return instance
    
    def __init__(self, name):
        print(f"__init__ called with self={self}, name={name}")
        self.name = name
        print("__init__ done")

p = Person("Alice")
# 输出:
# __new__ called with cls=<class '__main__.Person'>, name=Alice
# __new__ returns <__main__.Person object at 0x...>
# __init__ called with self=<__main__.Person object at 0x...>, name=Alice
# __init__ done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 参数和返回值

__new__:

  • 第一个参数是cls,是类本身,不是对象。
  • 必须返回一个对象。通常返回super().__new__(cls)。
  • 如果返回的不是当前类的实例,__init__不会被调用。

__init__:

  • 第一个参数是self,是已经创建好的对象。
  • 不应该有返回值(或返回None)。如果返回其他值,Python会报错。
  • 只负责设置属性,不负责创建对象。
class Test:
    def __new__(cls):
        print("Creating object")
        return super().__new__(cls)
    
    def __init__(self):
        print("Initializing object")
        self.value = 42

t = Test()
# 输出:
# Creating object
# Initializing object
1
2
3
4
5
6
7
8
9
10
11
12
13

# 为什么要分两个阶段

大多数情况下,你只需要重写__init__。但有些场景需要在对象创建时做特殊处理,这时就要重写__new__:

  1. 单例模式:确保类只创建一个实例。
  2. 继承不可变类型:int、str、tuple等不可变对象在__init__时已经不能修改,必须在__new__阶段定制。
  3. 元类和特殊对象:控制对象的创建过程。

__new__和__init__的执行流程

# 单例模式的实现

单例模式要求类只能创建一个实例。 通过重写__new__,检查是否已经创建过对象,如果有就返回已有对象:

class Singleton:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            print("Creating the only instance")
            cls._instance = super().__new__(cls)
        else:
            print("Returning existing instance")
        return cls._instance
    
    def __init__(self):
        print("__init__ called")

s1 = Singleton()  # Creating the only instance, __init__ called
s2 = Singleton()  # Returning existing instance, __init__ called
print(s1 is s2)   # True
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

注意:__init__每次都会被调用,即使返回的是同一个对象。如果不想重复初始化,需要加个标志位:

class Singleton:
    _instance = None
    _initialized = False
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def __init__(self):
        if not Singleton._initialized:
            print("First init")
            self.value = 42
            Singleton._initialized = True
        else:
            print("Already initialized")

s1 = Singleton()  # First init
s2 = Singleton()  # Already initialized
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 继承不可变类型

不可变类型(int、str、tuple)的值在创建后不能改变,所以不能在__init__里修改。必须在__new__阶段定制:

class PositiveInt(int):
    def __new__(cls, value):
        if value < 0:
            raise ValueError("Value must be positive")
        return super().__new__(cls, value)

p = PositiveInt(10)
print(p)  # 10

# p = PositiveInt(-5)  # ValueError: Value must be positive
1
2
3
4
5
6
7
8
9
10

int.__new__需要接收值作为参数,所以我们传递value。创建后,这个对象的值就固定了,__init__无法修改。

同样的,自定义tuple子类时,也要在__new__里定制:

class NamedPoint(tuple):
    def __new__(cls, x, y):
        return super().__new__(cls, (x, y))
    
    @property
    def x(self):
        return self[0]
    
    @property
    def y(self):
        return self[1]

point = NamedPoint(3, 4)
print(point)    # (3, 4)
print(point.x)  # 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# __new__返回其他类型会怎样

如果__new__返回的不是当前类的实例,__init__不会被调用:

class A:
    def __new__(cls):
        print("A.__new__")
        return "not an A instance"
    
    def __init__(self):
        print("A.__init__")

obj = A()
print(obj)       # not an A instance
print(type(obj)) # <class 'str'>
# 注意:A.__init__没有被调用
1
2
3
4
5
6
7
8
9
10
11
12

# 知识拓展

Q1:为什么大多数时候只重写__init__?

因为object.__new__已经够用了,它会创建一个空对象。我们只需要在__init__里添加属性。只有需要控制对象创建过程时(单例、不可变类型、工厂模式),才需要重写__new__。

Q2:__new__是类方法还是静态方法?

它是个特殊方法,行为像类方法(第一个参数是cls),但不需要@classmethod装饰器。Python解释器会自动把类传给__new__。

Q3:能在__init__里返回一个值吗?

不能。__init__返回除None以外的值会报TypeError:

class Test:
    def __init__(self):
        return 42  # TypeError: __init__() should return None
1
2
3

Q4:super().__new__(cls)为什么要传cls?

因为object.__new__是个静态方法风格的特殊方法,需要知道创建哪个类的实例。传入cls,它会返回cls类型的对象。

Q5:多继承时__new__和__init__怎么调用?

按照MRO(方法解析顺序)调用。如果多个父类都重写了__new__或__init__,Python会按C3线性化的顺序调用。使用super()可以确保按MRO调用下一个类的方法。


上一篇:实例方法、类方法和静态方法有什么区别?
下一篇:Python如何实现封装、继承和多态?

Last Updated: 10/13/2026, 5:57:00 PM

← 实例方法、类方法和静态方法有什么区别? Python如何实现封装、继承和多态? →

评论

验证登录状态...

侧边栏 侧边栏
夜间模式 夜间
卡码简历 卡码简历
代码随想录 代码随想录
卡码投递表 卡码投递表🔥
2026实习校招群 2026群
添加客服微信 2026实习校招客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记 支持卡码笔记
鼓励/支持/赞赏Carl 卡码笔记赞赏码
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪