python的__init__和__new__方法

我们平时都是定义类和方法都是这样的:

class People(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print('This is init')
    def func(self):
        print("This is Test Func")

if __name__ == '__main__':
    s = People('张三', 25)
    print(s.name)
    print(s.age)
    s.func()
    
# This is init
# 张三
# 25
# This is Test Func

但是在使用__init__()方法初始化之前还有一步,那就是__new__()创建实例!
那么什么是__new__()?
1.new()是在类准备将自身实例化时调用,并且至少需要传递一个参数cls,此参数在实例化时由python解释器自动提供;
2.始终是类的静态方法,即使没有被加上静态方法装饰器
3.必须要有返回值,返回实例化出来的实例;可以return父类(通过super(当前类名,cls)).__new__出来的实例,或者直接是object的__new__出来的实例

从object继承

class People(object):
    def __new__(cls, *args, **kwargs):
        print('This is __new__()')  # 这是为了追踪new的执行过程
        print(type(cls))  # 这是为了追踪new的执行过程
        return object.__new__(cls)  # 调用父类的(object)的new方法,返回一个People实例,这个实例传递给init的self参数

    def __init__(self, name, age):
        self.name = name
        self.age = age
        print('This is __init__()')

    def func(self):
        print("This is testfunc")


if __name__ == '__main__':
    s = People('Tom', 18)
    print(s.name)
    print(s.age)
    s.func()


# This is __new__()
# <class 'type'>
# This is __init__()
# Tom
# 18
# This is testfunc

从自定义的类继承

class People:
    def __new__(cls, *args, **kwargs):
        print("This is People's new")
        print(type(cls))
        return super(People,cls).__new__(cls)

    def __init__(self):
        print("This is People's init")


class Children(People):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print("This is Children's init")


if __name__ == '__main__':
    child = Children('Tom', 18)
    print(child.name)
    print(child.age)


# This is People's new
# <class 'type'>
# This is Children's init
# Tom
# 18

如果没有返回值,就不能够创建实例,那么在初始化init的时候自然会出错,这就是为什么会报错没有name属性,因为根本没创建成功

class People(object):
    def __new__(cls, *args, **kwargs):
        print('This is __new__()')  # 这是为了追踪new的执行过程
        print(type(cls))  # 这是为了追踪new的执行过程

    def __init__(self, name, age):
        self.name = name
        self.age = age
        print('This is __init__()')

    def func(self):
        print("This is testfunc")


if __name__ == '__main__':
    s = People('Tom', 18)
    print(s.name)
    print(s.age)
    s.func()

# print(s.name)
# AttributeError: 'NoneType' object has no attribute 'name'
# This is __new__()
# <class 'type'>

__new__不是一定要有的,只有继承自object的类才有,子类如果没有重新定义new,会直接追溯至object的new方法,因为object是所有新式类的基类。子类中如果新写了new,可以自由选择其他的新式类,这也是为什么我们平时没有写__new__也不会报错的原因:会直接追溯至object的new方法,因为object是所有新式类的基类!

init()方法
1.有一个参数self,该self参数就是__new__()返回的实例;

2.init()在__new()的基础上完成初始化动作,不需要返回值;

3.若__new__()没有正确返回当前类cls的实例,那__init__()将不会被调用

4.创建的每个实例都有自己的属性,方便类中的实例方法调用
5.init()至少有一个参数self,就是这个__new__()返回的实例__init__()在__new__()的基础上完成一些初始化的操作

总结:
1、创建实例的时候,先new后init
2、new定义在type元类中,必须具有返回值
3、new的作用就是创建实例,然后将创建的实例传递给init进行初始化
4、__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径,还有就是实现自定义的metaclass
5.自己在定义__new__的时候,参数要与__init__函数的参数匹配,我可以不用到这些参数,但一定要匹配。或者可以使用*arg和**args的形式:*arg可以匹配任意多个未知参数

猜你喜欢

转载自blog.csdn.net/liulanba/article/details/115252631