- 1.__new__(cls, *args, **kwargs) 建立對象時調用,是一個靜態方法,返回當前對象的一個實例; 注意:這裏的第一個參數是cls即class自己
- 2.__init__(self, *args, **kwargs) 建立完對象後調用,對當前對象的實例的一些初始化,無返回值,即在調用__new__以後,根據返回的實例初始化;注意,這裏的第一個參數是self即對象自己【注意和new的區別】
- 3.__call__(self, *args, **kwargs) 若是類實現了這個方法,至關於把這個類型的對象看成函數來使用,至關於 重載了括號運算符, 對象可call,注意不是類,是對象
先有建立,纔有初始化。即先__new__,然後__init__。
上面說的很差理解,看例子。python
1.對於__new__ide
class Bar(object): pass class Foo(object): def __new__(cls, *args, **kwargs): return Bar() print Foo()
能夠看到,輸出來是一個Bar對象。函數
__new__方法在類定義中不是必須寫的,若是沒定義,默認會調用object.__new__去建立一個對象。若是定義了,就是override,能夠custom建立對象的行爲。
聰明的讀者可能想到,既然__new__能夠custom對象的建立,那我在這裏作一下手腳,每次建立對象都返回同一個,那不就是單例模式了嗎?沒錯,就是這樣。能夠觀摩《飄逸的python - 單例模式亂彈》
定義單例模式時,由於自定義的__new__重載了父類的__new__,因此要本身顯式調用父類的__new__,即object.__new__(cls, *args, **kwargs),或者用super()。,否則就不是extend原來的實例了,而是替換原來的實例。代理
2.對於__init__code
使用Python寫過面向對象的代碼的同窗,可能對 __init__ 方法已經很是熟悉了,__init__ 方法一般用在初始化一個類實例的時候。例如:對象
# -*- coding: utf-8 -*- class Person(object): """Silly Person""" def __init__(self, name, age): self.name = name self.age = age def __str__(self): return '<Person: %s(%s)>' % (self.name, self.age) if __name__ == '__main__': piglei = Person('piglei', 24) print piglei
這樣即是__init__最普通的用法了。但__init__其實不是實例化一個類的時候第一個被調用 的方法。當使用 Persion(name, age) 這樣的表達式來實例化一個類時,最早被調用的方法 實際上是 __new__ 方法。blog
3.對於__call__
對象經過提供__call__(slef, [,*args [,**kwargs]])方法能夠模擬函數的行爲,若是一個對象x提供了該方法,就能夠像函數同樣使用它,也就是說x(arg1, arg2...) 等同於調用x.__call__(self, arg1, arg2) 。模擬函數的對象能夠用於建立防函數(functor) 或代理(proxy).utf-8
class Foo(object): def __call__(self): pass f = Foo()#類Foo可call f()#對象f可call
總結,在Python中,類的行爲就是這樣,__new__、__init__、__call__等方法不是必須寫的,會默認調用,若是本身定義了,就是override,能夠custom。既然override了,一般也會顯式調用進行補償以達到extend的目的。
這也是爲何會出現"明明定義def _init__(self, *args, **kwargs),對象怎麼不進行初始化"這種看起來詭異的行爲。(注,這裏_init__少寫了個下劃線,由於__init__不是必須寫的,因此這裏不會報錯,而是當作一個新的方法_init__)it