内置方法进阶__new__() 构造方法

new
在init之前,实例化对象的第一步是new创建了一个空间

为什么会自动先创建一个空间呢,就是所有的类实例化的时候都会创建一个内存地址,然后再执行init方法,这个空间就好比一个泥人,每个类创建的对象都是一个泥人
然后init来初始化类,就给这个泥人不同的形态。出现这种自动执行的机制是什么。原来在python中,所有的类都是object子类,都继承了object这个父类的所有方法和属性。
类中的普通属性,静态属性,类属性,property属性都可以继承吗,来简单试一下运行结果。

class A():
    @staticmethod   # 静态方法可继承
    def a():
        print(1)

    @classmethod   # 类方法可继承
    def c(cls):
        print(2)

    def __str__(self):   # 内置方法可继承
        return 'hhh'

class B(A):  # 创建A的子类
    pass

b = B()   # 创建A的子类的实例化对象
b.a()   # 1 # 父类的静态方法可继承
b.c()  # 2  # 父类中的类方法可继承
print(str(b))   # 父类中的内置方法可继承

事实证明,父类中的所有类型的方法子类都可以继承,也就是说子类的实例化对象都可以用父类中的所有属性和方法,既然object是所有类的父类,那么object中所有方法所有的类
都可以调用。那object中有哪些方法呢?
看看源码:

class object:
    """ The most base type """  # 最基础的类型,most最大的,也就是他是最大的boss,是所有类的祖宗
    .
    .   #中间省略一千字
    .
     def __init__(self):  # known special case of object.__init__
         """ Initialize self.  See help(type(self)) for accurate signature. """
         # 初识化self
         pass

    @staticmethod  # known case of __new__
    def __new__(cls, *more):  # known special case of object.__new__
        """ Create and return a new object.  See help(type) for accurate signature. """
        # 创造和返回一个新的对象。python底层用C++写的代码实现这个只要打印一个类名加括号就自动触发了这个方法,就开辟了一个对象空间
        pass

    ... # 省略,因为现在只关注object中的__new__方法

再看看是不是真的会先执行_new这个方法。

class Foo:
    def __init__(self):   # 初始化方法,给小人穿衣服
        print('执行了init')

    def __new__(cls, *args, **kwargs):  # 构造方法,捏小人
        object.__new__(cls)    # 找到父类object中的__new__(cls)方法并执行
        print('执行了new')   #
        return object.__new__(cls)   # 返回给执行者这个方法执行的结果,也就是开辟一个空间

obj = Foo()
>>>
执行了new  # 执行的结果证明创建对象时第一步自动执行__new__方法,原理是先在类空间找,如果没有就到父类空间找。所以一般创建类时不定义此方法还是创建了一个对象就是这个原因
执行了init   # 第一步执行了__init__(self)方法,所以有时没有在自己创建的类中设置这个方法也会初始化一下就是因为对象沿着类指针找到了object中的此方法,然后自动执行。

如果在常用的23种设计模式中实现单例模式,就是一个类只有一个实例的的时候

单例模式
class Foo:
    __instance = None  # 类中私有属性
    def __init__(self, name, age):  # 初始化方法
        self.name = name
        self.age = age
        self.lst = [name]

    def __new__(cls, *args, **kwargs):  # 构造方法,实例化对象时默认执行的第一步
        if cls.__instance is None:  # 如果该属性的值为None,也就是空或False
            cls.__instance = object.__new__(cls)   # 就执行这个赋值语句,先执行右边的创建一个对象空间,这个对象地址名赋值给私有变量,此时私有变量的值不为空。
        return cls.__instance  # 返回这个对象的地址给该类创建的对象。

obj1 = Foo('laura', 20)  # 第一次创建了一个对象,类中的__instance不为None
obj2 = Foo('wendy', 24)  # 第二次创建对象时,首先找到__new__方法并执行,发现此方法if下面的代码块执行不了,所以就直接跳过,执行__init__方法,也就是没有新创建一个对象空间给新的对象,而是改已经在对象空间中存在的属性。
print(obj1.lst, obj2.lst)  # ['wendy'] ['wendy']

这里写图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42233629/article/details/82353023