Python 建立類物件例項的過程
1、問題由來
有一次在類的定義時將一個方法外的屬性前加上了self
class Myclass(object):
self.test='hello' #錯誤使用self
def __init__(self, x):
self.x = x
c1 = Myclass(11)
執行時報錯:
Traceback (most recent call last): File "e:\Job\TSC\CodeCloud\classTest.py", line 40, in <module> class Myclass(object): File "e:\Job\TSC\CodeCloud\classTest.py", line 41, in Myclass self.test='hello' NameError: name 'self' is not defined
剛開始分析是因為類在初始化時尚未執行__init__( )函式,例項物件尚未建立起來,因此這麼定義會出錯。但是發現__init__(self, x )函式中以及傳入了self這個變數,說明例項已經建立。那麼Python中例項是什麼時候建立的呢?
2、Python中類的例項化過程
Python中存在著一種靜態的__new__()方法,通常在定義類時不會重寫__new__()方法,於是Python在呼叫類時會自動尋找該類的繼承物件(本例中為Object),然後返回當前類的例項物件:
def __new__(cls, *args, **kwargs): ... return object.__new__(cls) #執行object的__new__()函式
執行object的__new__()函式後會返回例項物件(self),然後將self作為第一個引數傳給該類的初始化方法__init__()方法。這裡self只是例項物件的一個名字,也是Python里約定俗成的一種叫法,可以自定義其名稱。
當執行c1 = Myclass(11)程式碼時其實做了兩個動作:
執行結果為:class Myclass(object): def __init__(self, x): self.x = x c1 = Myclass(11) #相當於隱式執行了__new__()和__init() c2 = Myclass.__new__(Myclass, 12) #顯式呼叫__new__(),返回c2物件 c2.__init__( 12) #顯示呼叫__init(),完成c2的初始化 print c1.x, c2.x
11 12
3、解決問題
瞭解物件的例項化後過程後可知在__init__()方法之前使用self是不允許的,可將test變數定義成類的屬性,這樣即可通過類也可以通過例項訪問test變數。
class Myclass(object):
test='hello'
def __init__(self, x):
self.x = x
c1 = Myclass(11) #例項化
print Myclass.test, c1.test
hello hello #輸出
4、__init__( )與C++中的建構函式
C++中建構函式的作用初始化物件的資料成員,該類例項物件被建立時,編譯系統為物件分配記憶體空間,並自動呼叫該建構函式,由建構函式完成成員的初始化工作。Python直譯器先使用類方法__new__( )為類分配空間,返回類例項,之後通過呼叫該物件的__init__( )方法初始化變數。
__init__( ) | 建構函式 | |
功能 | 初始化類變數 | 初始化類變數 |
返回值 | 沒有 | 沒有 |
過載 | 可以,子類調使用super.__init__()過載 | 可以 |
5、單例實現方法
單例就是說一個class只能有一個instance,實現的方法有很多種。
a、重新定義__new__方法(經典做法,支援多執行緒操作)
class Singleton(object):
_instance = None
def __new__(cls, *args, **kw):
'''object將__new__()方法定義為靜態方法,並且至少需要傳遞一個引數cls
cls表示需要例項化的類,此引數在例項化時由Python直譯器自動提供
'''
if not cls._instance:
print 'create Singleton instance'
cls._instance = super(Singleton, cls).__new__(cls, *args, **kw) #super函式幹啥的。。
else:
print 'instance Singleton exists'
return cls._instance
class A(Singleton):
_instance = None
def __new__(cls,*args,**kw):
if not cls._instance:
print 'create A instance'
cls._instance = super(A, cls).__new__(cls, *args, **kw)
else:
print 'instance A exists'
return cls._instance
def __init__(self):
print 'A'
A1=A()
A2=A()
輸出為:
create A instance #執行A的__new__函式
create Singleton instance #執行Singleton的__new__函式
A
instance A exists
A
b、使用裝飾器
def Singleton(cls):
_instance = {}
def _singleton(*args, **kargs):
if cls not in _instance:
print 'create instance'
_instance[cls] = cls(*args, **kargs)
else:
print 'instance exits'
return _instance[cls]
return _singleton
@Singleton
class A(object):
def __init__(self, x=0):
self.x = x
a1 = A(2)
a2 = A(3)
輸出為:
creat instance
instance exits