詳解Python中的__init__和__new__的區別

2021-03-02 日常學python

作者:小致dad

原文連結:https://my.oschina.net/liuyuantao/blog/747164

一、__init__ 方法是什麼?

使用Python寫過面向對象的代碼的同學,可能對 __init__ 方法已經非常熟悉了,__init__ 方法通常用在初始化一個類實例的時候。例如:


這樣便是__init__最普通的用法了。但__init__其實不是實例化一個類的時候第一個被調用 的方法。當使用 Persion(name, age) 這樣的表達式來實例化一個類時,最先被調用的方法 其實是 __new__ 方法。

二、__new__ 方法是什麼?

__new__方法接受的參數雖然也是和__init__一樣,但__init__是在類實例創建之後調用,而 __new__方法正是創建這個類實例的方法。


執行結果:

通過運行這段代碼,我們可以看到,__new__方法的調用是發生在__init__之前的。其實當 你實例化一個類的時候,具體的執行邏輯是這樣的:

1. p = Person(name, age)
2. 首先執行使用name和age參數來執行Person類的__new__方法,這個__new__方法會 返回Person類的一個實例(通常情況下是使用 super(Persion, cls).__new__(cls, ... ...) 這樣的方式),
3. 然後利用這個實例來調用類的__init__方法,上一步裡面__new__產生的實例也就是 __init__裡面的的 self


所以,__init__ 和 __new__ 最主要的區別在於:
1.__init__ 通常用於初始化一個新實例,控制這個初始化的過程,比如添加一些屬性, 做一些額外的操作,發生在類實例被創建完以後。它是實例級別的方法。
2.__new__ 通常用於控制生成一個新實例的過程。它是類級別的方法。
但是說了這麼多,__new__最通常的用法是什麼呢,我們什麼時候需要__new__?

三、__new__ 的作用

依照Python官方文檔的說法,__new__方法主要是當你繼承一些不可變的class時(比如int, str, tuple), 提供給你一個自定義這些類的實例化過程的途徑。還有就是實現自定義的metaclass。
首先我們來看一下第一個功能,具體我們可以用int來作為一個例子:
假如我們需要一個永遠都是正數的整數類型,通過集成int,我們可能會寫出這樣的代碼。

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

通過重載__new__方法,我們實現了需要的功能。
另外一個作用,關於自定義metaclass。其實我最早接觸__new__的時候,就是因為需要自定義 metaclass,但鑑於篇幅原因,我們下次再來講python中的metaclass和__new__的關係。

四、用__new__來實現單例

事實上,當我們理解了__new__方法後,我們還可以利用它來做一些其他有趣的事情,比如實現 設計模式中的 單例模式(singleton) 。
因為類每一次實例化後產生的過程都是通過__new__來控制的,所以通過重載__new__方法,我們 可以很簡單的實現單例模式。

輸出結果:


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

推薦閱讀:

用Python來跳Michael Jackson的太空漫步

用Python代碼來下載任意指定網易雲歌曲

日常學python

代碼不止bug,還有美和樂趣

相關焦點

  • 說說Python中的__new__和__init__的區別?
    如果參考答案不夠好,或者有錯誤的話,麻煩大家可以在留言區給出自己的意見和討論,大家是要一起學習的 。廢話不多說,開始今天的題目:問:說說Python中的__new__和__init__的區別?答:在Python中__new__和__init__具有不同的功能。
  • Python面試之理解__new__和__init__的區別
    中的__init__是構造方法,但其實不然,Python中真正的構造方法是__new__。__init__和__new__有什麼區別?本文就來探討一下。我們先來看一下__init__的用法class Person(object):    def __init__(self, name, age):        print("in __init__")        self.
  • python知識掃盲(1)-__init__與__new__的區別
    __new__中cls代表類,args為參數列表;__init__中self代表實例對象,args為參數列表。__new__方法是靜態方法,而__init__為實例方法。__new__方法一般返回類的對象,當返回類的對象時將會自動調用__init__方法進行初始化,如果沒有對象返回,則__init__方法不會被調用。
  • Python中__init__.py文件的作用詳解
    __init__.py 文件的作用是將文件夾變為一個Python模塊,Python 中的每個模塊的包中,都有__init__.py 文件。
  • Python小知識: __init__.py的作用
    __init__.py 文件的作用是將文件夾變為一個Python模塊,Python 中的每個模塊的包中,都有__init__.py 文件。通常__init__.py 文件為空,但是我們還可以為它增加其他的功能。我們在導入一個包時,實際上是導入了它的__init__.py文件。這樣我們可以在__init__.py文件中批量導入我們所需要的模塊,而不再需要一個一個的導入。
  • Python中classmethod和staticmethod的區別
    今天來寫一下裝飾器classmethod和staticmethod這兩個關鍵詞。
  • 詳解Python元類
    理解元類(metaclass)之前,我們先了解下Python中的OOP和類(Class)。面向對象全稱 Object Oriented Programming 簡稱OOP,這種編程思想被大家所熟知。它是把對象作為一個程序的基本單元,把數據和功能封裝在裡面,能夠實現很好的復用性,靈活性和擴展性。
  • Python 中常用的魔術方法
    博客地址:zhihu.com/people/zarten概述python中特殊方法(魔術方法)是被python解釋器調用的,我們自己不需要調用它們,我們統一使用內置函數來使用。而__init__()用來初始化實例,所以__new__()比__init___()先執行。
  • Python 2 與 Python 3 的區別
    最近的項目開始用Python3寫了,也體會了一下2和3的區別。xrangePython 2中有 range 和 xrange 兩個方法。其區別在於,range返回一個list,在被調用的時候即返回整個序列;xrange返回一個iterator,在每次循環中生成序列的下一個數字。Python 3中不再支持 xrange 方法,Python 3中的 range 方法就相當於 Python 2中的 xrange 方法。
  • Python數據類型
    這裡要說下, Python中沒有接口這個概念, 類似於接口, Python使用的是一種協議, 只要實現的這個協議, 並不一定需要去繼承某個抽象類, 就可以判定實現了協議的對象是某個抽象類的子類.Python中類型提示是3.x版本才有的, 在運行時不起作用, 默認編譯也是沒有影響的, 只有在IDE(pycharm)或者第三方檢查工具(mypy)才會使用.
  • Python和JAVA的區別
    區別:1.Python比Java簡單,學習成本低,開發效率高2.Java運行效率高於Python,尤其是純Python開發的程序,效率低3.Java相關資料多,尤其是中文資料一些細節區別:1.數python只有四種數據:整數,長整數、浮點數和複數 java則有char,short,byte,int,long,float,double類型2. 字符串2.1.
  • Python基礎篇-08 Python版本區別,Python 3和Python 2區別詳解
    公眾號關注「專攻python」,設為「星標」重磅文章,第一時間送達!!
  • Python中最基礎的面試題,這你都不會,就不再說Python簡單了
    下列哪個表達式在Python中是非法的?Linux中線程的調度由作業系統控制D. Linux中協程的調度由作業系統控制13. 下列哪種函式參數定義不合法?__foo解析器用_classname__foo來代替這個名字,以區別和其他類相同的命名C. __foo__代表python裡特殊方法專用的標識D. __foo 可以直接用於』from module import *』25.
  • Python 中 staticmethod 和 classmethod 原理探究
    起步文章Python 中 property 的實現原理及實現中探究了 property 的實現原理。如果能理解那邊描述符的使用方式,那也能很快理解本篇中的 staticmethod 和 classmethod 。
  • 很全的 Python 面試題
    在python中,strings, tuples, 和numbers是不可更改的對象,而list,dict等則是可以修改的對象。15 __new__和__init__的區別這個__new__確實很少見到,先做了解吧.__new__是一個靜態方法,而__init__是一個實例方法.__new__方法會返回一個創建的實例,而__init__什麼都不返回.只有在__new__返回一個cls的實例時後面的__init__才能被調用.
  • python傳參數./ - CSDN
    (三種方法:__init__,__new__,__call__)  當我們需要高度定製類的時候,如限制類名必須大寫開頭等等。。。。>元類中的new方法會在創建類對象時執行,並且先於init方法  作用是創建一個類對象   class A(metaclass=MyMetaClass): pass1.執行MyMetaClass的__new
  • Python __slots__ 詳解
    作者並沒有提到他的業務特點和代碼,那我們就基於《fluent python》中的例子來驗證下是不是有這麼厲害:from __future__ import print_functionimport resourceclass A(object):    def __init__(self):        self.a
  • C++ new A 和 new A() 的區別詳解
    那麼這兩種究竟有什麼區別呢?調用new分配的內存有時候會被初始化,而有時候不會,這依賴於A的類型是否是POD(Plain old data)類型,或者它是否是包含POD成員、使用編譯器生成默認構造函數的類。附:POD類型POD是Plain old data的縮寫,它是一個struct或者類,且不包含構造函數、析構函數以及虛函數。
  • Python中 __init__的通俗解釋
    前言作為典型的面向對象的語言,Python中 類 的定義和使用是不可或缺的一部分知識。
  • Python中模塊(Module)和包(Package)到底是什麼,有什麼區別?
    模塊(Module)在電腦程式的開發過程中,隨著程序代碼越寫越多,在一個文件裡代碼就會越來越長,越來越不容易維護。為了編寫可維護的代碼,我們把很多函數分組,分別放到不同的文件裡,這樣,每個文件包含的代碼就相對較少,很多程式語言都採用這種組織代碼的方式。在Python中,一個.py文件就稱之為一個模塊(Module)。