python學習筆記之面向對象編程特性(二)

面向對象程序設計中的術語對象(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是繼承了AB的,所以它可以調用Ama()方法,也可以調用Bmb()方法;但是當AB裏面有相同的方法時,它會優先去執行繼承的第一個超類。


四、繼承和重載:

#!/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才能被當做模塊導入

wKioL1dyUHDRhVDnAAAkZOnsfJk723.png


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文件,並把目錄下模塊文件的名字寫進去,在調用時多加一層目錄就可以了。

wKiom1dyUYDS0d2sAAAh0jliVNM456.png

下面示例一下里面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下面的語句,如果是當做程序來執行時,則會執行下面的語句,一般用作測試。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章