Python面試之理解__new__和__init__的區別

沈仲強發表於2018-04-23

很多同學都以為Python中的__init__是構造方法,但其實不然,Python中真正的構造方法是__new__。__init__和__new__有什麼區別?本文就來探討一下。

我們先來看一下__init__的用法

class Person(object):
    def __init__(self, name, age):
        print("in __init__")
        self._name = name
        self._age = age 

p = Person("Wang", 33) 

複製程式碼

上面的程式碼會輸出如下的結果

in __init__
<__main__.Person object at 0x7fb2e0936450>

複製程式碼

那麼我們思考一個問題,Python中要實現Singleton怎麼實現,要實現工廠模式怎麼實現? 用__init__函式似乎沒法做到呢~ 實際上,__init__函式並不是真正意義上的建構函式,__init__方法做的事情是在物件建立好之後初始化變數。真正建立例項的是__new__方法。 我們來看下面的例子

class Person(object):
    def __new__(cls, *args, **kwargs):
        print("in __new__")
        instance = object.__new__(cls, *args, **kwargs)
        return instance

    def __init__(self, name, age):
        print("in __init__")
        self._name = name
        self._age = age

p = Person("Wang", 33)

複製程式碼

上面的程式碼輸出如下的結果

in __new__
in __init__

複製程式碼

上面的程式碼中例項化了一個Person物件,可以看到__new__和__init__都被呼叫了。__new__方法用於建立物件並返回物件,當返回物件時會自動呼叫__init__方法進行初始化。__new__方法是靜態方法,而__init__是例項方法。 好了,理解__new__和__init__的區別後,我們再來看一下前面提出的問題,用Python怎麼實現Singleton,怎麼實現工廠模式? 先來看Singleton

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = object.__new__(cls, *args, **kwargs)

        return cls._instance

s1 = Singleton()
s2 = Singleton()
print(s1)
print(s2) 

複製程式碼

上面的程式碼輸出

<__main__.Singleton object at 0x7fdef58b1190>
<__main__.Singleton object at 0x7fdef58b1190>

複製程式碼

可以看到s1和s2都指向同一個物件,實現了單例模式。

再來看下工廠模式的實現

class Fruit(object):
    def __init__(self):
        pass

    def print_color(self):
        pass

class Apple(Fruit):
    def __init__(self):
        pass

    def print_color(self):
        print("apple is in red")

class Orange(Fruit):
    def __init__(self):
        pass

    def print_color(self):
        print("orange is in orange")

class FruitFactory(object):
    fruits = {"apple": Apple, "orange": Orange}

    def __new__(cls, name):
        if name in cls.fruits.keys():
            return cls.fruits[name]()
        else:
            return Fruit()

fruit1 = FruitFactory("apple")
fruit2 = FruitFactory("orange")
fruit1.print_color()    
fruit2.print_color()    

複製程式碼

上面的程式碼輸出

apple is in red
orange is in orange

複製程式碼

看完上面兩個例子,大家是不是對__new__和__init__的區別有了更深入的理解?

                                  歡迎關注微信公眾號【Python與資料分析】
複製程式碼

Python面試之理解__new__和__init__的區別

相關文章