詳解Python中的__new__、__init__、__call__三個特殊方法
__new__: 對象的創(chuàng)建,是一個靜態(tài)方法,第一個參數(shù)是cls。(想想也是,不可能是self,對象還沒創(chuàng)建,哪來的self)
__init__ : 對象的初始化, 是一個實例方法,第一個參數(shù)是self。
__call__ : 對象可call,注意不是類,是對象。
先有創(chuàng)建,才有初始化。即先__new__,而后__init__。
上面說的不好理解,看例子。
1.對于__new__
class Bar(object): pass class Foo(object): def __new__(cls, *args, **kwargs): return Bar() print Foo()
可以看到,輸出來是一個Bar對象。
__new__方法在類定義中不是必須寫的,如果沒定義,默認(rèn)會調(diào)用object.__new__去創(chuàng)建一個對象。如果定義了,就是override,可以custom創(chuàng)建對象的行為。
聰明的讀者可能想到,既然__new__可以custom對象的創(chuàng)建,那我在這里做一下手腳,每次創(chuàng)建對象都返回同一個,那不就是單例模式了嗎?沒錯,就是這樣。可以觀摩《飄逸的python - 單例模式亂彈》
定義單例模式時,因為自定義的__new__重載了父類的__new__,所以要自己顯式調(diào)用父類的__new__,即object.__new__(cls, *args, **kwargs),或者用super()。,不然就不是extend原來的實例了,而是替換原來的實例。
2.對于__init__
使用Python寫過面向?qū)ο蟮拇a的同學(xué),可能對 __init__ 方法已經(jīng)非常熟悉了,__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__其實不是實例化一個類的時候第一個被調(diào)用 的方法。當(dāng)使用 Persion(name, age) 這樣的表達(dá)式來實例化一個類時,最先被調(diào)用的方法 其實是 __new__ 方法。
3.對于__call__
對象通過提供__call__(slef, [,*args [,**kwargs]])方法可以模擬函數(shù)的行為,如果一個對象x提供了該方法,就可以像函數(shù)一樣使用它,也就是說x(arg1, arg2...) 等同于調(diào)用x.__call__(self, arg1, arg2) 。模擬函數(shù)的對象可以用于創(chuàng)建防函數(shù)(functor) 或代理(proxy).
class Foo(object): def __call__(self): pass f = Foo()#類Foo可call f()#對象f可call
總結(jié),在Python中,類的行為就是這樣,__new__、__init__、__call__等方法不是必須寫的,會默認(rèn)調(diào)用,如果自己定義了,就是override,可以custom。既然override了,通常也會顯式調(diào)用進(jìn)行補(bǔ)償以達(dá)到extend的目的。
這也是為什么會出現(xiàn)"明明定義def _init__(self, *args, **kwargs),對象怎么不進(jìn)行初始化"這種看起來詭異的行為。(注,這里_init__少寫了個下劃線,因為__init__不是必須寫的,所以這里不會報錯,而是當(dāng)做一個新的方法_init__)
相關(guān)文章
使用python3.0?對接美團(tuán)接口的實現(xiàn)示例
本文主要介紹了python3.0?對接美團(tuán)接口的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05python 數(shù)據(jù)類型強(qiáng)制轉(zhuǎn)換的總結(jié)
這篇文章主要介紹了python 數(shù)據(jù)類型強(qiáng)制轉(zhuǎn)換的使用總結(jié),幫助大家更好的理解和使用python,感興趣的朋友可以了解下2021-01-01Python中字符串類型代碼的執(zhí)行函數(shù)——eval()、exec()和compile()詳解
這篇文章主要介紹了Python中字符串類型代碼的執(zhí)行函數(shù)——eval()、exec()和compile(),字符串類型代碼的執(zhí)行函數(shù)有三個,都是Python的內(nèi)置函數(shù),下面逐一對這三個函數(shù)詳細(xì)講解,需要的朋友可以參考下2023-02-02Python讀取txt內(nèi)容寫入xls格式excel中的方法
今天小編就為大家分享一篇Python讀取txt內(nèi)容寫入xls格式excel中的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10Python分析和處理excel文件數(shù)據(jù)的詳細(xì)步驟
Python 提供了多種工具來分析和處理 Excel 文件數(shù)據(jù),最常用的庫包括 pandas、openpyxl 和 xlrd,本文將詳細(xì)介紹如何使用這些工具讀取、處理和分析 Excel 文件中的數(shù)據(jù),需要的朋友可以參考下2025-05-05詳解Python如何實現(xiàn)Excel數(shù)據(jù)讀取和寫入
這篇文章主要為大家詳細(xì)介紹了python如何實現(xiàn)對EXCEL數(shù)據(jù)進(jìn)行讀取和寫入,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04