python基本定制之__new__, __init__
1,官方文档摘要
调用以创建一个 cls 类的新实例。
__new__()
是一个静态方法 (因为是特例所以你不需要显式地声明),它会将所请求实例所属的类作为第一个参数。其余的参数会被传递给对象构造器表达式 (对类的调用)。__new__()
的返回值应为新对象实例 (通常是 cls 的实例)。典型的实现会附带适宜的参数使用super().__new__(cls[, ...])
,通过超类的__new__()
方法来创建一个类的新实例,然后根据需要修改新创建的实例再将其返回。如果__new__()
返回一个 cls 的实例,则新实例的__init__()
方法会在之后被执行,例如__init__(self[,...])
,其中 self 为新实例,其余的参数与被传递给__new__()
的相同。如果__new__()
未返回一个 cls 的实例,则新实例的__init__()
方法就不会被执行。__new__()
的目的主要是允许不可变类型的子类 (例如 int, str 或 tuple) 定制实例创建过程。它也常会在自定义元类中被重载以便定制类创建过程。
object.``__init__
(self[, ...])在实例 (通过
__new__()
) 被创建之后,返回调用者之前调用。其参数与传递给类构造器表达式的参数相同。一个基类如果有__init__()
方法,则其所派生的类如果也有__init__()
方法,就必须显式地调用它以确保实例基类部分的正确初始化;例如:super().__init__([args...])
.因为对象是由__new__()
和__init__()
协作构造完成的 (由__new__()
创建,并由__init__()
定制),所以__init__()
返回的值只能是None
,否则会在运行时引发TypeError
。
2,代码演示
class Students: # 用于初始化实例,相当于java的构造函数 def __init__(self): print('init方法') print(self) print(id(self)) """ __new__用法 用于创建实例,在创建实例的时候自动调用,相当于java的new Xxx() 1,cls表示当前类Students 2,super().__new__(cls)表示创建当前类Students类的实例,并返回这个实例 3,self接受__new__返回的实例,为当前类创建的实例本身,当执行student = Students(),self即为student """ def __new__(cls, *args, **kwargs): print('new方法') print(cls) print(id(cls)) a = super().__new__(cls) print(a) print(id(a)) return a # 设计单例模式 # def __new__(cls, *args, **kwargs): # if not hasattr(cls, 'instance'): # cls.instance = super().__new__(cls) # return cls.instance
print(id(Students)) student = Students() print(student) print(id(student))
执行的结果:
""" 193802760 new方法 <class '__main__.Students'> 193802760 <__main__.Students object at 0x0B8C9CB0> 193764528 init方法 <__main__.Students object at 0x0B8C9CB0> 193764528 <__main__.Students object at 0x0B8C9CB0> 193764528 """
3,总结
init 和 new 最主要的区别在于:
1.init 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。
2.new 通常用于控制生成一个新实例的过程。它是类级别的方法。new方法主要是当你继承一些不可变的class时(比如int, str, tuple),
提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。