0 前置知识
【菜鸟教程】super() 函数
【Python笔记】class, class()和class(object)的区别
1 自建实例
# -*- coding: utf-8 -*-
class Student(object):
def __new__(cls, name, class_no):
print('__new__ called.')
return super(Student, cls).__new__(cls)
#return super().__new__(cls) Python3可以省略super()中的内容
def __init__(self, name, class_no):
print('__init__ called.')
self.name = name
self.class_no = class_no
def __str__(self):
return '<Person: %s(%s)>' % (self.name, self.class_no)
if __name__ == '__main__':
# 实例化
stu1= Student('Peter Pan', 11)
print(stu1.name)
2 输出
实例化后,输出:
__new__ called.
__init__ called.
<Person: Peter Pan(11)>
结果说明
- 调用顺序:
__new__
方法的调用发生在__init__
之前。 - 实例化一个类的执行逻辑:
① stu1= Student(‘Peter Pan’, 11);
② 执行name和class_no参数执行Person类__new__
方法,这个__new__
方法会返回Person类的一个实例(通常情况下是使用return super(Student, cls).__new__(cls)
这样的方式);
③利用这个实例来调用类的__init__
方法,上一步里面__new__
产生的实例就是__init__
里面的self
。 __init__
和__new__
最主要的区别在于:
①__init__
通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。
②__new__
通常用于控制生成一个新实例的过程。它是类级别的方法。
__new__
至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
__new__
必须要有返回值,返回实例化出来的实例,这点在自己实现__new__
时要特别注意,可以return
父类__new__
出来的实例,或者直接是object的__new__
出来的实例
可以将类比作制造商,new方法就是前期的原材料购买环节,__init__
方法就是在有原材料的基础上,加工,初始化商品环节
3 什么时候需要__new__
如果在class Student()
的括号内不加object,则无需__new__
# -*- coding: utf-8 -*-
class Student():
# def __new__(cls, name, class_no):
# print('__new__ called.')
# return super(Student, cls).__new__(cls)
def __init__(self, name, class_no):
print('__init__ called.')
self.name = name
self.class_no = class_no
def __str__(self):
return '<Person: %s(%s)>' % (self.name, self.class_no)
if __name__ == '__main__':
name = Student('Peter Pan', 11)
print(name)
__init__ called.
<Person: Peter Pan(11)>
__new__
方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。
具体我们可以用int来作为一个例子:
假如我们需要一个永远都是正数的整数类型:
class PositiveInteger(int):
def __init__(self, value):
# 这里__init__()不能加任何参数
# 否则会报错TypeError: object.__init__() takes exactly one argument (the instance to initialize)
# 因为父类 int 中没有任何参数,所以不能传入参数
super().__init__()
# def __new__(cls, value):
# return super(PositiveInteger, cls).__new__(cls,abs(value))
if __name__ == '__main__':
# 实例化
i = PositiveInteger(-3)# -3
print(i)
通过重载__new__
方法,我们实现了需要的功能。
class PositiveInteger(int):
def __new__(cls, value):
return super(PositiveInteger, cls).__new__(cls,abs(value))
if __name__ == '__main__':
# 实例化
i = PositiveInteger(-3) # 3
print(i)
Reference:https://www.jianshu.com/p/08d7956601de