python 關於 __new__ , __init__ , cls, self 的碎碎念。

本文旨在澄清 python 裏 __new__ vs __init__cls vs self 的概念。 python

不少初學者會困擾,python的「魔法函數」 __new__ 有啥用? 跟__init__有啥區別? 爲何有的函數第一個輸入變量是self, 有的倒是cls? 這有啥區別?函數

好,廢話很少說,先看一個例子:code

class A(object):
    def __new__(cls):
        print("A.__new__ called")
        return super(A, cls).__new__(cls)

    def __init__(self):
        print("A.__init__ called")

A()
print('finished')

運行結果爲:orm

A.__new__ called
A.__init__ called
finished

爲何結果是這樣呢?
由於:__new__ 負責建立一個 object;以後 __init__ 負責初始化這個 object。it

有點繞是吧,再說具體點:io

A()被 call 的時候,__new__ 就自動執行了, 它建立了一個object(class的具體實例)並返回這個object,而後__init__接手這個實例再接着執行。 form

每當__new__ 建立並返回一個實例時,__init__ 就接手這個實例而後執行,這個實例就是__init__ 的第一個輸入變量,永遠不變的, 默認的self。 說到這裏,self怎麼來的應該很清楚了吧。class

在日常應用中,咱們定義某個class時幾乎不會去寫它的__new__方法,因而當咱們call這個class時,python會一直往上追溯到有__new__的父輩class, 一般咱們自定義的class都是object的子類,因此執行的都是它的__new__
object__new__建立並返回的這個實例,是裸的。 而後咱們的class__init__再接手這個裸的實例去進一步加工,好比加上各類 self.xxx = xxx, 或再執行一些別的code, 這個過程就是initialization。注意它和creation的區別,應該說的很清晰了吧。變量

那假如咱們本身定義一個壞了的__new__, 它沒有返回一個實例,這事會發生什麼呢?好比:object

class A(object):
    def __new__(cls):
        print("A.__new__ called")
        #return super(A, cls).__new__(cls)

    def __init__(self):
        print("A.__init__ called")

A()

運行一下,發現結果是:

A.__new__ called
finished

哈哈固然啦,__new__沒有返回一個建立好的實例,那麼__init__天然就執行不了了。 上頭沒有提供食材,廚子就揭不開鍋作飯嘛。

這個時候有人會問了,爲啥 __init__() 裏面是 self, 而__new__()裏面是cls呢?

首先,咱們澄清一下概念:

一、self表示一個具體的實例(instance)自己。(若是用了@staticmethod,那麼就能夠無視這個self,由於staticmethod就能夠理解成一個普通的函數)

二、cls表示這個類(class)自己。

OK, __init__() 裏面的self已經說清楚了,是剛剛__new__出爐的一個建立好的實例(object / instance); 那__new__()裏面是cls又是指哪一個class呢?

簡單說來:哪一個class召喚了__new__, cls就默認是哪一個class

再看一個例子 (Singleton 單例模式的實現):

class Singleton(object):

    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)

            print('\n')
            print('cls is ', cls)
            print(type(cls._instance),  cls._instance)

        else:
            print(' {}  already exists'.format(cls._instance))
        return cls._instance


class Bus(Singleton):
    def sendData(self,data):
        pass


class BusSon(Bus):
    def sendData(self,data):
        pass


if __name__ == '__main__':

    busson1 = BusSon()
    bus1 = Bus()
    print('------------------------\n')

    busson2 = BusSon()
    bus2 = Bus()

    print('------------------------\n')


    Bus.__new__(BusSon)
    Bus()
    x = Singleton.__new__(Bus)
    print(x)
相關文章
相關標籤/搜索