Python's __init__ and __new__ methods

We usually define classes and methods like this:

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

But there is one more step before using the __init__() method to initialize, and that is to create an instance of __new__()!
So what is __new__()?
1. new () is called when the class is ready to instantiate itself, and at least one parameter cls needs to be passed, which is automatically provided by the python interpreter when instantiating;
2. It is always a static method of the class, even if it is not added Upper static method decorator
3. Must have a return value to return the instantiated instance; you can return the parent class (via super(current class name, cls)).__new__ instance, or directly __new__ of object Examples coming out

Inherit from 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

Inherit from a custom class

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

If there is no return value, the instance cannot be created, so an error will naturally occur when initializing init, which is why an error is reported without the name attribute, because the creation was not successful at all

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__ is not necessary, only the class inherited from object, if the subclass does not redefine new, it will be directly traced back to the new method of object, because object is the base class of all new-style classes. If you write new in the subclass, you can freely choose other new-style classes. This is why we usually do not write __new__ and will not report an error: it will be directly traced back to the new method of object, because object is all new-style classes Base class!

init () method
1. There is a parameter self, which is the instance returned by __new__();

2. init () completes the initialization action on the basis of __new() and does not need to return a value;

3. If __new__() does not correctly return an instance of the current class cls, then __init__() will not be called

4. Each instance created has its own attributes, which is convenient for calling the instance method in the class.
5. Init () has at least one parameter self, which is the instance returned by this __new__() __init__() in __new__() Complete some initial operations on the basis

Summary:
1. When creating an instance, first new and then init
2. New is defined in the type metaclass and must have a return value
3. The role of new is to create an instance, and then pass the created instance to init for initialization
4. __new__ The method is mainly to provide you with a way to customize the instantiation process of these classes when you inherit some immutable classes (such as int, str, tuple), and to implement a custom metaclass
5. You are defining _ When _new__, the parameters must match the parameters of the __init__ function, I can not use these parameters, but they must match. Or you can use the form of *arg and **args: *arg can match any number of unknown parameters

Guess you like

Origin blog.csdn.net/liulanba/article/details/115252631