Python中的__new__、__init__、__call__三個特殊方法

HuangZhang_123發表於2017-03-31

歡迎加入學習交流QQ群:657341423


new: 物件的建立,是一個靜態方法,第一個引數是cls。(想想也是,不可能是self,物件還沒建立,哪來的self)
init : 物件的初始化, 是一個例項方法,第一個引數是self。
call : 物件可call,注意不是類,是物件。
先有建立,才有初始化。即先__new__,而後__init__。
直接看程式碼:

class Bar(object): 
  pass
  
class Foo(object): 
  def __new__(cls, *args, **kwargs): 
    return Bar() 
  
print Foo()
 可以看到,輸出來是一個Bar物件。

通俗一點就是,當你例項化一個物件的時候,就會執行__new__ 方法裡面的方法。__new__方法在類定義中不是必須寫的,如果沒定義,預設會呼叫object.__new__去建立一個物件。如果定義了,就是override,可以custom建立物件的行為。

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 方法。

call 這個看程式碼意會

#call.py 一個class被載入的情況下。
class Next:
  List = []
   
  def __init__(self,low,high) :
    for Num in range(low,high) :
      self.List.append(Num ** 2)
   
  def __call__(self,Nu):
    return self.List[Nu]

如果 這樣使用:

b = Next(1,7)
print b.List
print b(2)
輸出
[1, 4, 9, 16, 25, 36]
9

但如果這樣使用:

b = Next
b(1,7)
print b.List
print b(2)
$python ./call.py
[1, 4, 9, 16, 25, 36]
 
Traceback (most recent call last):
 File "cal.py", line 17, in <module>
  print b(2) 
TypeError: __init__() takes exactly 3 arguments (2 given)

__init__是初始化函式,在生成類的例項時執行。
而__call__是模擬()的呼叫,需要在例項上應用,因此這個例項自然是已經執行過__init__了。
你所舉的後面那個例子:
b = Next
這並不是建立例項,而是將class賦給一個變數。因此後面使用b進行的操作都是對Next類的操作,那麼其實就是:

Next(1,7)
print Next.List
print Next(2)

相關文章