【Python笔记】__new__() & __init__() 方法的区别

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)>

结果说明

  1. 调用顺序: __new__方法的调用发生在__init__ 之前。
  2. 实例化一个类的执行逻辑:
    ① stu1= Student(‘Peter Pan’, 11);
    ② 执行name和class_no参数执行Person类__new__方法,这个__new__方法会返回Person类的一个实例(通常情况下是使用return super(Student, cls).__new__(cls) 这样的方式);
    ③利用这个实例来调用类的__init__ 方法,上一步里面__new__产生的实例就是 __init__ 里面的self
  3. __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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值