面向對象程序設計中的術語對象(Object)基本上可以看做數據(特性)以及由一系列可以存取、操作這些數據的方法所組成的集合。傳統意義上的“程序=數據結構+算法”被封裝”掩蓋“並簡化爲“程序=對象+消息”。對象是類的實例,類的抽象則需要經過封裝。封裝可以讓調用者不用關心對象是如何構建的而直接進行使用。
首先說明一下python編程規範:
#!/usr/bin/env python #coding=utf-8 #編程規範,示例如下: class ClassName(object): '''testdoc #這裏面是一些說明文檔,該類的說明信息是可以被help看到的 example: ''' #註釋的寫法,可以在後面,也可以在上一行,單行註釋以#號開頭 a= 100 #this is a number for a #thisis a number for b b= 200 c= ['a','b'] #or 分行寫 d= { #列表、字典等可以分行寫,這樣更加直觀 'key1':'v1', 'key2':'v2', 'key3':'v3' } def__init__(self,num,m): #初始化方法。如果不寫,則是從基類繼承 self.age= num self.__money= m deftest(self): return100 def__eq__(self,other): #魔術方法 returnself.age == other.age def__del__(self): #析構函數,在整個類調用執行完後會執行 print'world' d = Hello(2,200) d2 = Hello(3,100) print d == d2 #會自動調用__eq__方法,返回比較結果 print d print d2
書寫規範一般從 說明文、初始化方法、單行或多行註釋等
一、構造方法:
下面示例說明了構造方法和初始化方法的執行順序:
#!/usr/bin/env python class Of(object): def __new__(cls,*args,**kwargs): #構造方法 print 'new' return super(Of,cls).__new__(cls,*args,**kwargs) #returnobject.__new__(cls,*args,**kwargs) def __init__(self): #初始化方法 print "init" def test(self): print 'hello' f = Of()
執行結果如下:
new init
說明了類在實例化時會先執行構造方法,再去執行初始化方法
下面的示例說明了構造方法和初始化方法的區別:
#!/usr/bin/env python class Resource(object): #父類的定義 def __init__(self): #初始化方法,爲了說明這裏直接輸出名字 print 'call me resource init' def __new__(cls,*args,**kwargs): #構造方法,這裏使用這種傳參可以接受任何類型的參數 print "resource new" returnobject.__new__(cls,*args,**kwargs) #返回值爲object基類的構造方法的返回值 class DockerResource(Resource): #子類的定義,繼承了Resource類 def __new__(cls,*args,**kwargs): #重新構造自己的構造方法 print "call me dockerresource new" returnResource.__new__(cls,*args,**kwargs) #返回值爲Resource父類的構造方法的返回值 def __init__(self): #定義自己的初始化方法 print 'call docker resourceinit' def test(self): #定義test方法 print 'dosker resource test' r = DockerResource() #實例化DockerResource,並將返回值傳遞給r print r #打印r,查看返回值是什麼 print type(r) #查看r的類型 r.test()
輸出結果如下:
call me docker resource new #首先調用了DockerResource的構造方法 resource new #構造方法返回的是Resource的構造方法,所以會執行Resource父類構造方法的print "resource new" call docker resource init #然後會執行自己的初始化方法 <__main__.DockerResource object at0x7fa1a3edcf90> #r現在接受的是Resource父類的構造方法的返回值,所以會有object出現 <class '__main__.DockerResource'> #類型爲自己DockerResource dosker resource test #調用自己的test方法
在類中,首先會執行自己的構造方法,如果沒有就會從父類繼承,然後會執行自己的初始化方法,沒有還是會從父類中繼承,接下來就可以正常調用自己的實例方法了
二、繼承:
下面的示例說明了子類繼承父類
#!/usr/bin/env python class Resource(object): #定義一個父類,繼承於object基類 def __new__(cls,*args,**kwargs): #構造方法 print 'class resource __new__' obj =super(Resource,cls).__new__(cls,*args,**kwargs) #利用super函數找到自己的父類,並將它的構造方法傳遞給obj print obj.__class__ #打印obj的類型 return obj #返回值爲obj def __init__(self): #初始化方法 print "call me init forResource" def test(self): print "call me test forResource" def create(self): print "call me create forResource" class subResource(Resource): #定義子類,繼承Resource父類 def __init__(self): #定義自己的初始化方法 print 'sub resource init' def test(self): print 'sub resource test' class Heat(object): #定義一個Heat類,繼承於基類object,是個新式類 def __new__(cls,*args,**kwargs): #定義自己的構造方法 print "class __new__%s" % cls returnobject.__new__(cls,*args,**kwargs) #返回值爲object基類的構造方法的返回值 def __init__(self): #定義初始化方法 print 'heat init' r = Heat() #實例化 print r h = Resource() #實例化 print h f = subResource() #實例化 print f
執行結果如下:
class __new__ <class '__main__.Heat'> #實例化Heat類,首先執行自己的構造方法和初始化方法,所以先輸出構造方法的print語句 heat init #執行了自己的初始化方法 <__main__.Heat object at0x7f43349ac050> #r實例化後繼承的是object基類,打印返回值 class resource __new__ #實例化Resource類,首先執行自己的構造方法和初始化方法,所以先輸出構造方法的print語句 <class '__main__.Resource'> #打印父類構造方法的返回值的類名 call me init for Resource #執行自己的初始化方法 <__main__.Resource object at0x7f43349ac090> # h實例化後繼承的是object基類,打印返回值 class resource __new__ #實例化subResource類,首先執行父類的構造方法,所以先輸出父類構造方法的print語句 <class '__main__.subResource'> #父類構造方法裏面打印自己的類名 sub resource init #執行自己的初始化方法 <__main__.subResource object at0x7f43349ac0d0> #f實例化後是執行了父類Resource類的構造方法,返回的依舊是object基類
三、多重繼承:
#!/usr/bin/env python class A(object): def __init__(self): pass def ma(self): print 'a.ma' def m(self): print 'it is A' class B(object): def mb(self): print 'b.mb' def m(self): print 'it is B' class C(A,B): pass c = C() c.ma() c.mb() c.m()
執行結果如下:
a.ma b.mb it is A
通過執行結果,我們可以看出,C是繼承了A和B的,所以它可以調用A的ma()方法,也可以調用B的mb()方法;但是當A和B裏面有相同的方法時,它會優先去執行繼承的第一個超類。
四、繼承和重載:
#!/usr/bin/env python class Phone(object): def __init__(self,size,color,memory): self.size = size self.color = color self.memory = memory def call(self): s = 'I can call' return s def sms(self): s = 'Are you gua le mei?' #!/usr/bin/env python class Phone(object): def __init__(self,size,color,memory): self.size = size self.color = color self.memory = memory def call(self): s = 'I can call' return s def sms(self): s = 'Are you gua le mei?' return s class Phones(Phone): #繼承了Phone類,重載了自己的初始化方法,又增加了自己的方法,既擁有超類的方法,又有自己特有的方法 def __init__(self,size,color,memory,pix): self.pix = pix super(Phones,self).__init__(size,color,memory) def install_app(self,app): s = 'install %s' % app return s class Huwei(Phone): #繼承了Phone類,又增加了自己的方法,既擁有超類的方法,又有自己特有的方法 def weixin(self,msg): if msg.find('gcd') == -1: return 'sending....' else: return 'You can\'t sendthe msg' p = Phone(1.2,'black','4M') #實例化 iphone =Phones(4.7,'white','4G','1280*766') #實例化 h = Huwei(4.7,'yellow','4G') #實例化 print iphone.install_app('weixin') #執行特有的install_app方法 print h.sms() print h.call() print h.weixin('wansui') sms = p.sms() call = p.call() print sms,call
執行結果如下:
install weixin Are you gua le mei? I can call sending.... Are you gua le mei? I can call
方法的重載實際上就是在類中使用def關鍵字重載父類的方法。如果重載父類中的方法,但又需要
在類中使用父類的該方法,可以使用父類名加‘ .’加方法名的形式調用
五、魔術方法:
#!/usr/bin/env python class Information(object): '''This is a doc #說明文檔 example for test,please don'tchange it. ''' def __init__(self,sch,cla,m,n): #定義初始化方法 print "welecome to schoolsystem." self.school = sch #實例變量 self.cla***oom = cla #實例變量 self.num = 100 #實例變量 self.__money = m #私有變量 self.num = n #實例變量 def school_name(self): #返回實例變量,即將實例變量傳遞出去 return self.school def class_name(self): #返回實例變量,即將實例變量傳遞出去 return self.cla***oom def class_money(self): #返回私有變量,即將私有變量傳遞出去 return self.__money #魔術方法:以雙下劃線開頭,以雙下劃線結尾的方法是魔術方法 def __eq__(self,another): #當外部出現'=='比較的時候,調用此魔術方法 return self.__money ==another.__money #返回兩個私有變量的比較結果(布爾值),這裏self是'=='左邊的參數值,another是右邊的參數值 def __gt__(self,another): #當外部出現'>'比較的時候,調用此魔術方法 return self.__money >another.__money #返回兩個私有變量的比較結果(布爾值),這裏self是'>'左邊的參數值,another是右邊的參數值 def __ne__(self,another): #當外部出現'!='比較的時候,調用此魔術方法 return self.__money !=another.__money #返回兩個私有變量的比較結果(布爾值),這裏self是'!='左邊的參數值,another是右邊的參數值 def __add__(self,another): #當外部出現'+'運算符的時候,調用此魔術方法 return self.__money +another.__money #返回兩個私有變量的相加結果,這裏self是'!='左邊的參數值,another是右邊的參數值 #returnInformation('jiaoda','dz1302',self.__money + another.__money) #return Information('jiaoda','dz1302',1024,self.num+ another.num) def __str__(self): return 'money = %d' %self.__money def __hash__(self): #獲取hash值 return 1314521 def __getattr__(self,name): #當調用不存在的方法時,執行此方法進行輸出 print "get attr %s" %name return name def __del__(self): #析構方法,當不再使用此類時,會自動執行 print "Goodbye,welecomhere again." f = Information('youdian','tg1312',9999,6) #實例化 l = Information('ligong','jk1213',6666,4) #實例化 print f == l #調用魔術方法__eq__() print f + l #調用魔術方法__add__() print f > l #調用魔術方法__gt__() s = f + l # print s print f.ccc #名字不存在,調用__getatter__()方法
__str__是被print函數調用的,一般都是return一個什麼東西。這個東西應該是以字符串的形式表現的。如果不是要用str()函數轉換。當你打印一個類的時候,那麼print首先調用的就是類裏面的定義的__str__
執行結果如下:
welecome to school system. #首先會在實例化的時候執行初始化方法 welecome to school system. #第二次實例化調用初始化方法 False #打印__eq__()的返回值爲False 16665 #打印__add__()的返回值爲兩數相加 True #打印__gt__()的返回值爲True 16665 get attr ccc #執行__getattr__()方法 ccc Goodbye,welecom here again. #執行完會自動執行析構函數 Goodbye,welecom here again.
六、模塊:
在python中,自帶200多個模塊,現在經過大家的不斷完善以及改進,官網已經收集了兩千多庫模塊,幾乎可以實現任何你想要的功能。
在我們自己使用時,也可以使用自己的模塊,任何一個.py都可以作爲一個單獨的模塊進行導入;
現在我們首先定義一個自己的模塊:module.py
#!/usr/bin/env python #coding=utf-8 def test(): print'This is a test' def test2(): print'test2' class DB(object): def__init__(self): self.a= 101 deftest(self): returnself.a
在同一目錄下,打開python交互式就可以導入這個模塊,名字就是文件的名module;
在文件中寫入進行導入調用,,,,,這裏是在同一目錄下(同一層)
#!/usr/bin/env python import module module.test()
結果如下:
This is a test
改進一下,進行調用模塊中的類:
#!/usr/bin/env python import module h = module.DB() print h.test()
輸出結果如下:
101
下面我們試着去導入一個目錄下的模塊:
新建一個目錄heat,在裏面寫入幾個模塊文件
目錄下必須有__init__.py才能被當做模塊導入
在heat目錄下的docker.py內容爲:
#!/usr/bin/env python def docker(): return'This is a docker in heat' class Docker(object): defcreate_c(self): return'1314521aaa' defstop_c(self): return'it is stop' print __name__ if __name__ == '__main__': print__name__ d= Docker()
在heat目錄下的nova.py內容爲:
#!/usr/bin/env python def nova(): return'This is a nova' class Nova(object): deftest(self): return'This is a test in nova'
現在heat目錄下只是有__init__這個文件,文件裏面無內容
寫一個調用的腳本文件:
#!/usr/bin/env python #coding=utf-8 import heat.docker #目錄下__init__.py裏面沒有__all__ printheat.docker.docker()
執行結果如下:
heat.docker This is a docker in heat This is a docker in heat
現在只能導入目錄下的具體的模塊,像上面一樣導入和調用;
爲了將目錄下的所有模塊文件都可以被導入,可以在目錄下的__init__.py裏面加下以下內容:
__all__ = ['docker','nova'] #將所有模塊名字寫入
改變執行文件內容:
#!/usr/bin/env python #coding=utf-8 import heat.docker #目錄下__init__.py裏面沒有__all__ print heat.docker.docker() from heat import * #heat目錄下__init__裏面內容是:__all__ = ['docker',nova'] print docker.docker() print nova.nova() n = nova.Nova() print n.test()
執行結果如下:
heat.docker This is a docker in heat This is a docker in heat This is a nova This is a test in nova
如果在目錄下還有目錄裏面存在需要導入的模塊,可以繼續在裏面寫__init__.py文件,並把目錄下模塊文件的名字寫進去,在調用時多加一層目錄就可以了。
下面示例一下里面mod.py文件內容:
#!/usr/bin/env python #coding=utf-8 def hello(): return'hello everyone' class Hello(object): def__init__(self): self.a= 103 deftest(self): return'This is a test in Hello'
執行下面的腳本進行測試:
#!/usr/bin/env python #coding=utf-8 from heat.common import mod print mod.hello() h = mod.Hello() print h.test()
執行結果如下:
hello everyone This is a test in Hello
如果需要裏面的所有模塊文件,還是繼續在__init__.py文件裏寫入就好了。
需要注意的是,文件被當做模塊導入時,會產生.pyc文件,如果更改了模塊,應該刷新.pyc文件,否則讀取的還是舊信息。
爲了防止文件是被作爲模塊使用的,我們應該在文件中加入
if __name__ == '__main__': pass #這裏是要執行的語句
這樣就可以防止當文件是被用作模塊使用時,不會被執行if下面的語句,如果是當做程序來執行時,則會執行下面的語句,一般用作測試。