Python 面向對象編程(一)


                      Python 面向對象編程(一)

  雖然Python是解釋性語言,但是它是面向對象的,能夠進行對象編程。下面就來了解一下如何在Python中進行對象編程。

一.如何定義一個類

  在進行python面向對象編程之前,先來了解幾個術語:類,類對象,實例對象,屬性,函數和方法。

  類是對現實世界中一些事物的封裝,定義一個類可以采用下面的方式來定義:

class className:
    block

  注意類名后面有個冒號,在block塊里面就可以定義屬性和方法了。當一個類定義完之后,就產生了一個類對象。類對象支持兩種操作:引用和實例化。引用操作是通過類對象去調用類中的屬性或者方法,而實例化是產生出一個類對象的實例,稱作實例對象。比如定義了一個people類:

class people:
    name = 'jack'       #定義了一個屬性
    #定義了一個方法
    def printName(self):
        print self.name

  people類定義完成之后就產生了一個全局的類對象,可以通過類對象來訪問類中的屬性和方法了。當通過people.name(至於為什么可以直接這樣訪問屬性后面再解釋,這里只要理解類對象這個概念就行了)來訪問時,people.name中的people稱為類對象,這點和C++中的有所不同。當然還可以進行實例化操作,p=people( ),這樣就產生了一個people的實例對象,此時也可以通過實例對象p來訪問屬性或者方法了(p.name).

  理解了類、類對象和實例對象的區別之后,我們來了解一下Python中屬性、方法和函數的區別。

  在上面代碼中注釋的很清楚了,name是一個屬性,printName( )是一個方法,與某個對象進行綁定的函數稱作為方法。一般在類里面定義的函數與類對象或者實例對象綁定了,所以稱作為方法;而在類外定義的函數一般沒有同對象進行綁定,就稱為函數。

二.屬性

  在類中我們可以定義一些屬性,比如:

class people:
    name = 'jack'
    age = 12

p = people()
print p.name,p.age

  定義了一個people類,里面定義了name和age屬性,默認值分別為'jack'和12。在定義了類之后,就可以用來產生實例化對象了,這句p = people( )實例化了一個對象p,然后就可以通過p來讀取屬性了。這里的name和age都是公有的,可以直接在類外通過對象名訪問,如果想定義成私有的,則需在前面加2個下划線 ' __'。

class people:
    __name = 'jack'
    __age = 12

p = people()
print p.__name,p.__age

  這段程序運行會報錯:

  

  提示找不到該屬性,因為私有屬性是不能夠在類外通過對象名來進行訪問的。在Python中沒有像C++中public和private這些關鍵字來區別公有屬性和私有屬性,它是以屬性命名方式來區分,如果在屬性名前面加了2個下划線'__',則表明該屬性是私有屬性,否則為公有屬性(方法也是一樣,方法名前面加了2個下划線的話表示該方法是私有的,否則為公有的)。

三.方法

  在類中可以根據需要定義一些方法,定義方法采用def關鍵字,在類中定義的方法至少會有一個參數,,一般以名為'self'的變量作為該參數(用其他名稱也可以),而且需要作為第一個參數。下面看個例子:

class people:
    __name = 'jack'
    __age = 12

    def getName(self):
        return self.__name
    def getAge(self):
        return self.__age

p = people()
print p.getName(),p.getAge()

  

  如果對self不好理解的話,可以把它當做C++中類里面的this指針一樣理解,就是對象自身的意思,在用某個對象調用該方法時,就將該對象作為第一個參數傳遞給self。

四.類中內置的方法

  在Python中有一些內置的方法,這些方法命名都有比較特殊的地方(其方法名以2個下划線開始然后以2個下划線結束)。類中最常用的就是構造方法和析構方法。

  構造方法__init__(self,....)在生成對象時調用,可以用來進行一些初始化操作,不需要顯示去調用,系統會默認去執行。構造方法支持重載,如果用戶自己沒有重新定義構造方法,系統就自動執行默認的構造方法。

  析構方法__del__(self)在釋放對象時調用,支持重載,可以在里面進行一些釋放資源的操作,不需要顯示調用。

  還有其他的一些內置方法:

  比如 __cmp__( ), __len( )__等,具體的用法可以參考這篇博文:

  http://www.cnblogs.com/simayixin/archive/2011/05/04/2036295.html

五.類屬性、實例屬性、類方法、實例方法以及靜態方法

  在了解了類基本的東西之后,下面看一下python中這幾個概念的區別。

  先來談一下類屬性和實例屬性

  在前面的例子中我們接觸到的就是類屬性,顧名思義,類屬性就是類對象所擁有的屬性,它被所有類對象的實例對象所共有,在內存中只存在一個副本,這個和C++中類的靜態成員變量有點類似。對於公有的類屬性,在類外可以通過類對象和實例對象訪問。

class people:
    name = 'jack'  #公有的類屬性
    __age = 12     #私有的類屬性

p = people()

print p.name             #正確
print people.name        #正確
print p.__age            #錯誤,不能在類外通過實例對象訪問私有的類屬性
print people.__age       #錯誤,不能在類外通過類對象訪問私有的類屬性

  實例屬性是不需要在類中顯示定義的,比如:

class people:
    name = 'jack'

p = people()
p.age =12
print p.name    #正確
print p.age     #正確

print people.name    #正確
print people.age     #錯誤

  在類外對類對象people進行實例化之后,產生了一個實例對象p,然后p.age = 12這句給p添加了一個實例屬性age,賦值為12。這個實例屬性是實例對象p所特有的,注意,類對象people並不擁有它(所以不能通過類對象來訪問這個age屬性)。當然還可以在實例化對象的時候給age賦值。

class people:
    name = 'jack'
    
    #__init__()是內置的構造方法,在實例化對象時自動調用
    def __init__(self,age):
        self.age = age

p = people(12)
print p.name    #正確
print p.age     #正確

print people.name    #正確
print people.age     #錯誤

  如果需要在類外修改類屬性,必須通過類對象去引用然后進行修改。如果通過實例對象去引用,會產生一個同名的實例屬性,這種方式修改的是實例屬性,不會影響到類屬性,並且之后如果通過實例對象去引用該名稱的屬性,實例屬性會強制屏蔽掉類屬性,即引用的是實例屬性,除非刪除了該實例屬性。

class people:
    country = 'china'
    

print people.country
p = people()
print p.country
p.country = 'japan' 
print p.country      #實例屬性會屏蔽掉同名的類屬性
print people.country
del p.country    #刪除實例屬性
print p.country

  

  

  下面來看一下類方法、實例方法和靜態方法的區別。

  類方法:是類對象所擁有的方法,需要用修飾器"@classmethod"來標識其為類方法,對於類方法,第一個參數必須是類對象,一般以"cls"作為第一個參數(當然可以用其他名稱的變量作為其第一個參數,但是大部分人都習慣以'cls'作為第一個參數的名字,就最好用'cls'了),能夠通過實例對象和類對象去訪問。

class people:
    country = 'china'
    
    #類方法,用classmethod來進行修飾
    @classmethod
    def getCountry(cls):
        return cls.country

p = people()
print p.getCountry()    #可以用過實例對象引用
print people.getCountry()    #可以通過類對象引用

  類方法還有一個用途就是可以對類屬性進行修改:

class people:
    country = 'china'
    
    #類方法,用classmethod來進行修飾
    @classmethod
    def getCountry(cls):
        return cls.country
        
    @classmethod
    def setCountry(cls,country):
        cls.country = country
        

p = people()
print p.getCountry()    #可以用過實例對象引用
print people.getCountry()    #可以通過類對象引用

p.setCountry('japan')   

print p.getCountry()   
print people.getCountry()    

  運行結果:

  

  結果顯示在用類方法對類屬性修改之后,通過類對象和實例對象訪問都發生了改變。

  

  實例方法:在類中最常定義的成員方法,它至少有一個參數並且必須以實例對象作為其第一個參數,一般以名為'self'的變量作為第一個參數(當然可以以其他名稱的變量作為第一個參數)。在類外實例方法只能通過實例對象去調用,不能通過其他方式去調用。

class people:
    country = 'china'
    
    #實例方法
    def getCountry(self):
        return self.country
        

p = people()
print p.getCountry()         #正確,可以用過實例對象引用
print people.getCountry()    #錯誤,不能通過類對象引用實例方法

  靜態方法:需要通過修飾器"@staticmethod"來進行修飾,靜態方法不需要多定義參數。

class people:
    country = 'china'
    
    @staticmethod
    #靜態方法
    def getCountry():
        return people.country
        

print people.getCountry()     

 

  對於類屬性和實例屬性,如果在類方法中引用某個屬性,該屬性必定是類屬性,而如果在實例方法中引用某個屬性(不作更改),並且存在同名的類屬性,此時若實例對象有該名稱的實例屬性,則實例屬性會屏蔽類屬性,即引用的是實例屬性,若實例對象沒有該名稱的實例屬性,則引用的是類屬性;如果在實例方法更改某個屬性,並且存在同名的類屬性,此時若實例對象有該名稱的實例屬性,則修改的是實例屬性,若實例對象沒有該名稱的實例屬性,則會創建一個同名稱的實例屬性。想要修改類屬性,如果在類外,可以通過類對象修改,如果在類里面,只有在類方法中進行修改。

  從類方法和實例方法以及靜態方法的定義形式就可以看出來,類方法的第一個參數是類對象cls,那么通過cls引用的必定是類對象的屬性和方法;而實例方法的第一個參數是實例對象self,那么通過self引用的可能是類屬性、也有可能是實例屬性(這個需要具體分析),不過在存在相同名稱的類屬性和實例屬性的情況下,實例屬性優先級更高。靜態方法中不需要額外定義參數,因此在靜態方法中引用類屬性的話,必須通過類對象來引用。

  關於面向對象編程暫時就講這么多了,其他關於類的繼承和方法重載這些內容將在后面繼續講解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM