一、init 方法是什么?

init 方法通常用在初始化一个类实例的时候。例如:

class Person(object):
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

if __name__ == '__main__':
    zs = Person("张三", 24, "男")
    print(zs)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

这是init最常见的用法。但init其实不是实例化一个类的时候第一个被调用 的方法。当使用 Persion(name,age,sex) 这样的表达式来实例化一个类时,最先被调用的方法 其实是 new 方法。

二、new 方法是什么?

new方法接受的参数虽然也是和init一样,但init是在类实例创建之后调用,而 new方法正是创建这个类实例的方法。

class Person(object):

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __new__(cls, name, age):
        if 18 < age < 60:
            # new()方法是在类准备将自身实例化时调用。
            # new()方法始终都是类的静态方法,即使没有被加上静态方法装饰器。
            return object.__new__(cls)
            # return super(Person, cls).__new__(cls)
        else:
            return None

    def __str__(self):
        return '{0}({1})'.format(self.__class__.__name__, self.__dict__)

print(Person('Tom', 30))
print(Person('Mike', 200))
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

输出结果为:

Person({'name': 'Tom', 'age': 30})
None
  • 1.
  • 2.

通过运行这段代码,我们可以看到,new方法的调用是发生在init之前的。其实当 你实例化一个类的时候,具体的执行逻辑是这样的:

1. p = Person(name, age)
2. 首先执行使用name和age参数来执行Person类的__new__方法,这个__new__方法会 返回Person类的一个实例
3. 然后利用这个实例来调用类的__init__方法,上一步里面__new__产生的实例也就是 __init__里面的的 self
  • 1.
  • 2.
  • 3.

所以,initnew 最主要的区别在于:

  • init 通常用于初始化一个新的实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。
  • newnew方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass