init和new有什么区别,new方法的返回值是什么


在Python中,__new__和__init__是对象创建与初始化的关键方法,两者在功能、调用顺序和返回值上有显著区别。以下是详细分析:

1. 核心区别

(1)作用不同

new

负责创建对象实例,分配内存空间,并返回新创建的实例。它是静态方法,直接操作类级别的行为,例如控制实例化过程或返回其他类型的对象。

init

负责初始化对象属性,在实例已创建后设置初始状态。它是实例方法,通过self参数操作对象属性。

一句话简单概括:__new__方法创建并返回实例,__init__初始化实例

(2)调用顺序

  • __new__先于__init__调用。

执行顺序,先执行__new__方法,再执行__init__方法

当通过类名实例化对象时,首先调用__new__方法创建实例,然后将该实例作为__init__的self参数进行初始化。

class MyClass:
	def __init__(self):
		print("__init__ running")

	def __new__(cls):
		print("__new__ running")
		return super().__new__(cls)

instance= MyClass()
#__new__ running
#__init__ running

(3)参数与返回值
在这里插入图片描述
关键点:

  • 若__new__未正确返回实例,__init__不会执行。
  • __new__可返回其他类的实例(如返回list对象),此时__init__可能不会被调用。
class MyClass:
	def __new__(cls):
		print("__new__ running")
		instance = super().__new__(cls)
		# return instance

	def __init__(self):
		print("__init__ running")
	



instance= MyClass()

# __new__ running

(4)new__方法构造一个类实例,并将该实例传递给自身的__init()方法,即__init__()方法的self参数。

class MyClass:
	def __new__(cls):
		print("__new__ running")
		instance = super().__new__(cls)
		print(instance)
		print(type(instance))
		print(id(instance))
		print("\n")
		return instance

	def __init__(self):
		print("__init__ running")
		print(self)
		print(type(self))
		print(id(self))



instance= MyClass()

# __new__ running
# <__main__.MyClass object at 0x000001C906EFCBB0>
# <class '__main__.MyClass'>
# 1962916432816


# __init__ running
# <__main__.MyClass object at 0x000001C906EFCBB0>
# <class '__main__.MyClass'>
# 1962916432816

(5)如果重写__new__方法,除了cls参数外,还需保持和__init__的其他入参一致

class MyClass:
	def __new__(cls):
		print("__new__ running")
		instance = super().__new__(cls)
		return instance

	def __init__(self,name,age):
		print("__init__ running")
		self.name =name
		self.age = age

instance= MyClass('YANG',99)

#Traceback (most recent call last):
#  File "xxx.py", line 14, in <module>
#    instance= MyClass('YANG',99)
#TypeError: __new__() takes 1 positional argument but 3 were given

正确应该这样写:

class MyClass:
	def __new__(cls,name,age):
		print("__new__ running")
		instance = super().__new__(cls)
		return instance

	def __init__(self,name,age):
		print("__init__ running")
		self.name =name
		self.age = age

instance= MyClass('YANG',99)

或者,推荐这样写:

class MyClass:
	def __new__(cls,*args,**kwargs):
		print("__new__ running")
		instance = super().__new__(cls)
		return instance

	def __init__(self,name,age):
		print("__init__ running")
		self.name =name
		self.age = age

instance= MyClass('YANG',99)



2. __new__的返回值

  • 必须返回一个对象实例:

通常通过super.new(cls)调用父类方法创建实例,并返回该实例。若返回非对象类型(如None或基本数据类型),则__init__不会执行。
特殊场景:

  • 单例模式:通过判断实例是否存在,决定是否创建新实例。
  • 工厂模式:根据参数返回不同子类的实例。
  • 继承不可变类型:如自定义int子类时,需在__new__中固定值。

3. 典型应用场景

1.单例模式

class Singleton:
    _instance = None
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super.__new__(cls)
        return cls._instance

通过__new__确保全局仅有一个实例。
2.不可变类型继承

class PositiveInt(int):
    def __new__(cls, value):
        return super.__new__(cls, abs(value))  # 强制值为正数

在__new__中修改参数以控制对象创建。
3.工厂模式
通过__new__根据参数返回不同子类实例,实现动态对象生成。

# 可以应用到不同数据库的连接上
class Shape:
    def __new__(cls, type_, *args, **kwargs):
        if type_ == "circle":
            instance = super.__new__(Circle)
        elif type_ == "square":
            instance = super.__new__(Square)
        else:
            raise ValueError(f"Unknown shape type: {type_}")
        
        # 初始化实例(可选)
        instance.type = type_
        return instance

class Circle(Shape):
    def __init__(self, radius):
        self radius = radius
        print(f"Circle created with radius {radius}")

class Square(Shape):
    def __init__(self, side):
        self侧长 = side
        print(f"Square created with side {side}")

# 使用工厂模式创建对象
circle = Shape("circle", radius=5)  # 输出: Circle created with radius 5
square = Shape("square", side=4)    # 输出: Square created with side 4

print isinstance(circle, Circle)    # 输出: True
print isinstance(square, Square)    # 输出: True

实现原理:

  • new 方法:在基类 Shape 中重写 new,根据传入的 type_ 参数决定创建哪个子类实例。
  • 动态实例化:通过 super.new(子类) 直接调用子类的构造方法,确保对象类型正确。
  • 参数传递:*args 和 **kwargs 会自动传递给子类的 init 方法。

优点:

  • 集中控制对象创建:所有对象创建逻辑在基类中统一管理。
  • 类型安全:通过 type_ 参数限制可创建的类型,避免非法实例。
  • 扩展性强:新增子类时只需修改 new 中的条件判断,无需修改调用代码。

对比传统工厂模式
传统工厂模式通常通过类方法(如 create)实现,而 new 方法直接拦截实例化过程,更符合Python的面向对象特性。

4. 总结对比表

在这里插入图片描述
通过理解两者的分工,可以更灵活地控制对象生命周期。通常情况下,仅需重写__init__进行初始化;而__new__适用于需要深度定制实例化逻辑的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值