So easy:Python中的__new__、__init__、__call__

(望結交天下才士 ,Contact:UVEgMTkwNDUyOTQzOA==)python

__new__: 對象的建立,是一個靜態方法,第一個參數是cls。(想一想也是,不多是self,對象還沒建立,哪來的self)
__init__ : 對象的初始化, 是一個實例方法,第一個參數是self。
__call__ : 對象可call,注意不是類,是對象。ide

先有建立,纔有初始化。即先__new__,然後__init__。
上面說的很差理解,看例子。函數

1.對於__new__spa

1 class Bar(object):
2   pass
3   
4 class Foo(object):
5   def __new__(cls, *args, **kwargs): 
6     return Bar()
7   
8 print Foo()

 能夠看到,輸出來是一個Bar對象。代理

__new__方法在類定義中不是必須寫的,若是沒定義,默認會調用object.__new__去建立一個對象。若是定義了,就是override,能夠custom建立對象的行爲。
聰明的讀者可能想到,既然__new__能夠custom對象的建立,那我在這裏作一下手腳,每次建立對象都返回同一個,那不就是單例模式了嗎?沒錯,就是這樣。能夠觀摩《飄逸的python - 單例模式亂彈》
定義單例模式時,由於自定義的__new__重載了父類的__new__,因此要本身顯式調用父類的__new__,即object.__new__(cls, *args, **kwargs),或者用super()。,否則就不是extend原來的實例了,而是替換原來的實例。code

2.對於__init__對象

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

 1 # -*- coding: utf-8 -*-
 2  
 3 class Person(object):
 4   """Silly Person"""
 5  
 6   def __init__(self, name, age):
 7     self.name = name
 8     self.age = age
 9  
10   def __str__(self):
11     return '<Person: %s(%s)>' % (self.name, self.age)
12  
13 if __name__ == '__main__':
14   piglei = Person('piglei', 24)
15   print piglei

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

3.對於__call__
對象經過提供__call__(slef, [,*args [,**kwargs]])方法能夠模擬函數的行爲,若是一個對象x提供了該方法,就能夠像函數同樣使用它,也就是說x(arg1, arg2...) 等同於調用x.__call__(self, arg1, arg2) 。模擬函數的對象能夠用於建立防函數(functor) 或代理(proxy).it

1 class Foo(object):
2   def __call__(self): 
3     pass
4   
5 f = Foo()#類Foo可call 
6 f()#對象f可call

總結,在Python中,類的行爲就是這樣,__new__、__init__、__call__等方法不是必須寫的,會默認調用,若是本身定義了,就是override,能夠custom。既然override了,一般也會顯式調用進行補償以達到extend的目的。這也是爲何會出現"明明定義def _init__(self, *args, **kwargs),對象怎麼不進行初始化"這種看起來詭異的行爲。(注,這裏_init__少寫了個下劃線,由於__init__不是必須寫的,因此這裏不會報錯,而是當作一個新的方法_init__)

相關文章
相關標籤/搜索