python3學習筆記-- __new__

先看一段代碼:

class Person:

    def __new__(cls, name, age):
        print('__new__ called.')

        return super(Person, cls).__new__(cls)

    def __init__(self, name, age):
        print('__new__ called.')
        self.name = name
        self.age = age

    def __str__(self):
        return '<Person: %s(%s)>' % (self.name, self.age)


if __name__ == '__main__':
    p = Person('p', 24)
    print(p)

程序運行結果:

__new__ called.
__new__ called.
<Person: p(24)>

可以看出,Foo類實例化f對象時首先會運行__new__方法,再運行__init___方法。__init__不是類實例化的內置方法嗎?爲什麼又多出個__new__? 它爲什麼會在__init__方法之前運行?它是幹嘛的?

一、__new__與__init__幹嘛的

__new__:類的實例化方法,並返回該實例

__init__:實例的構造方法, 接受類的實例(self)並對其進行構造

繼承自object的新式類纔有__new__

__new__至少要有一個參數cls,代表要實例化的類,此參數在實例化時由Python解釋器自動提供

__new__必須要有返回值,返回實例化出來的實例,這點在自己實現__new__時要特別注意,可以return父類__new__出來的實例,或者直接是object的__new__出來的實例

__init__有一個參數self,就是這個__new__返回的實例,__init__在__new__的基礎上可以完成一些其它初始化的動作,__init__不需要返回值

若__new__沒有正確返回當前類cls的實例,那__init__是不會被調用的,即使是父類的實例也不行


二、__new__的作用:

1. 自定義不可變的class如:int, str, tuple,  還有就是實現自定義的metaclass。

metaclass屬於神級魔法,目前沒有掌握在此放下不表。我們看下第一個功能。

以int爲例。假如我們需要一個永遠都是正數的整數類型,通過繼承int,我們可能會這樣寫代碼。

class PositiveInteger(int):
    def __init__(self, value):
        super(PositiveInteger, self).__init__(self, abs(value))
 
i = PositiveInteger(-3)
print(i)

但是運行後發現,結果根本不是我們想要的那樣,我們任然得到-3。這是因爲對於int這種不可變的對象,我們只有重載它的__new__方法才能起到自定義的作用。

修改代碼:

class PositiveInteger(int):
    def __new__(cls, value):
        return super(PositiveInteger, cls).__new__(cls, abs(value))
 
i = PositiveInteger(-3)
print(i)

通過重載__new__方法,我們實現了需要的功能。

2. 用__new__來實現單例

如何實現單例,面試常考。媽蛋,想想自己面試第一次回答這個問題的時候就想笑,明明沒聽過單例模式傻不啦嘰的說了一大堆,面試官就聽着不說話,我以爲自己說得特對。回來百度下才直到自己蠢到家了,渣渣。

因爲類每一次實例化後產生的過程都是通過__new__來控制的,所有通過重載__new__方法,我們可以很簡單的實現單例模式。

class Singleton:
    instance = None

    def __new__(cls, xx, yy):
        if cls.instance is None:
            cls.instance = super().__new__(cls)
        return cls.instance

    def __init__(self, xx, yy):
        self.xx = xx
        self.yy = yy


obj1 = Singleton(1, 2)
obj2 = Singleton(2, 1)


print(obj1.xx, obj2.xx)
print(obj1 is obj2)
輸出結果:
2 2
True

可以看到obj1, obj2是同一個實例。


參考博客:

https://blog.csdn.net/four_infinite/article/details/52806594

https://www.cnblogs.com/nyist-xsk/p/8286941.html

發佈了20 篇原創文章 · 獲贊 27 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章