python物件導向

2022-06-23 23:15:11 字數 4944 閱讀 9839

1、python中建立類屬性

類是模板,而例項則是根據類建立的物件。

繫結在一個例項上的屬性不會影響其他例項,但是,類本身也是一個物件,如果在類上繫結一個屬性,則所有例項都可以訪問類的屬性,並且,所有例項訪問的類屬性都是同一個!也就是說,例項屬性每個例項各自擁有,互相獨立,而類屬性有且只有一份。

定義類屬性可以直接在 class 中定義:

class

person(object):

address = '

earth

'def

__init__

(self, name):

self.name = name

因為類屬性是直接繫結在類上的,所以,訪問類屬性不需要建立例項,就可以直接訪問:

print

person.address

#=> earth

對一個例項呼叫類的屬性也是可以訪問的,所有例項都可以訪問到它所屬的類的屬性:

p1 = person('

bob'

)p2 = person('

alice')

print

p1.address

#=> earth

print

p2.address

#=> earth

由於python是動態語言,類屬性也是可以動態新增和修改的:

person.address = '

china

'print

p1.address

#=> 'china'

print

p2.address

#=> 'china'

因為類屬性只有一份,所以,當person類的address改變時,所有例項訪問到的類屬性都改變了。

2、python中類屬性和例項屬性名字衝突怎麼辦

修改類屬性會導致所有例項訪問到的類屬性全部都受影響,但是,如果在例項變數上修改類屬性會發生什麼問題呢?

class

person(object):

address = '

earth

'def

__init__

(self, name):

self.name =name

p1 = person('

bob'

)p2 = person('

alice')

print

'person.address =

' +person.address

p1.address = '

china

'print

'p1.address =

' +p1.address

print

'person.address =

' +person.address

print

'p2.address =

' + p2.address

結果如下:

person.address =earth

p1.address =china

person.address =earth

p2.address = earth

我們發現,在設定了 p1.address = 'china' 後,p1訪問 address 確實變成了 'china',但是,person.address和p2.address仍然是'earch',怎麼回事?

原因是 p1.address = 'china'並沒有改變 person 的 address,而是給 p1這個例項繫結了例項屬性address ,對p1來說,它有一個例項屬性address(值是'china'),而它所屬的類person也有一個類屬性address,所以:

訪問 p1.address 時,優先查詢例項屬性,返回'china'。

訪問 p2.address 時,p2沒有例項屬性address,但是有類屬性address,因此返回'earth'。

可見,當例項屬性和類屬性重名時,例項屬性優先順序高,它將遮蔽掉對類屬性的訪問。

當我們把 p1 的 address 例項屬性刪除後,訪問 p1.address 就又返回類屬性的值 'earth'了:

del

p1.address

print

p1.address

#=> earth

可見,千萬不要在例項上修改類屬性,它實際上並沒有修改類屬性,而是給例項繫結了一個例項屬性。

3、python中定義例項方法

一個例項的私有屬性就是以__開頭的屬性,無法被外部訪問,那這些屬性定義有什麼用?

雖然私有屬性無法從外部訪問,但是,從類的內部是可以訪問的。除了可以定義例項的屬性外,還可以定義例項的方法。

例項的方法就是在類中定義的函式,它的第一個引數永遠是 self,指向呼叫該方法的例項本身,其他引數和一個普通函式是完全一樣的:

class

person(object):

def__init__

(self, name):

self.

__name =name

defget_name(self):

return self.__name

get_name(self) 就是一個例項方法,它的第一個引數是self。__init__(self, name)其實也可看做是一個特殊的例項方法。

呼叫例項方法必須在例項上呼叫:

p1 = person('

bob'

)print p1.get_name() #

self不需要顯式傳入

#=> bob

在例項方法內部,可以訪問所有例項屬性,這樣,如果外部需要訪問私有屬性,可以通過方法呼叫獲得,這種資料封裝的形式除了能保護內部資料一致性外,還可以簡化外部呼叫的難度.

練習:

請給 person 類增加一個私有屬性 __score,表示分數,再增加一個例項方法 get_grade(),能根據 __score 的值分別返回 a-優秀, b-及格, c-不及格三檔。

#

-*- coding:utf-8-*-

class

person(object):

def__init__

(self, name, score):

self.

__name=name

self.

__score=score

defget_grade(self):

if self.__score>=80:

return

"a-優秀

"elif self.__score>=60:

return

"b-及格

"return

"c-不及格

"p1 = person('

bob', 90)

p2 = person('

alice

', 65)

p3 = person('

tim', 48)

print

p1.get_grade()

print

p2.get_grade()

print p3.get_grade()

4、python中方法也是屬性

我們在 class 中定義的例項方法其實也是屬性,它實際上是一個函式物件:

class

person(object):

def__init__

(self, name, score):

self.name =name

self.score =score

defget_grade(self):

return'a

'p1 = person('

bob', 90)

print

p1.get_grade

#=> >

print

p1.get_grade()

#=> a

也就是說,p1.get_grade 返回的是一個函式物件,但這個函式是一個繫結到例項的函式,p1.get_grade() 才是方法呼叫。

因為方法也是一個屬性,所以,它也可以動態地新增到例項上,只是需要用 types.methodtype() 把一個函式變為一個方法:

import

types

deffn_get_grade(self):

if self.score >= 80:

return'a

'if self.score >= 60:

return'b

'return'c

'class

person(object):

def__init__

(self, name, score):

self.name =name

self.score =score

p1 = person('

bob', 90)

p1.get_grade =types.methodtype(fn_get_grade, p1, person)

print

p1.get_grade()

#=> a

p2 = person('

alice

', 65)

print

p2.get_grade()

#error: attributeerror: 'person' object has no attribute 'get_grade'

# 因為p2例項並沒有繫結get_grade
給一個例項動態新增方法並不常見,直接在class中定義要更直觀。

面向切面語言

面向切面語言 aop為aspect oriented programming的縮寫,意為 面向切面程式設計,通過預編譯方式和執行期動態 實現程式功能的統一維護的一種技術。 aop與oop是面向不同領域的兩種設計思想。 oop 物件導向程式設計 針對業務處理過程的實體及其屬性和行為進行抽象封裝,以獲得更加清晰...

面向介面程式設計

面向介面程式設計 一般在實現一個系統的時候 通常是將定義與實現合為一體 不加分離的,我認為最為理解的系統設計規範應該是所有的定義與實現分離,...

面向切面程式設計

面向切面程式設計 aop是aspect oriented program的首字母縮寫 ,我們知道,物件導向的特點是繼承 多型和封裝。而封裝就...