1. 程式人生 > >Python 建立類物件例項的過程

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