1、python中建立類屬性
類是模板,而例項則是根據類建立的物件。
繫結在一個例項上的屬性不會影響其他例項,但是,類本身也是一個物件,如果在類上繫結一個屬性,則所有例項都可以訪問類的屬性,並且,所有例項訪問的類屬性都是同一個!也就是說,例項屬性每個例項各自擁有,互相獨立,而類屬性有且只有一份。
定義類屬性可以直接在 class 中定義:
classperson(object):
address = '
earth
'def
__init__
(self, name):
self.name = name
因為類屬性是直接繫結在類上的,所以,訪問類屬性不需要建立例項,就可以直接訪問:
person.address
#=> earth
對一個例項呼叫類的屬性也是可以訪問的,所有例項都可以訪問到它所屬的類的屬性:
p1 = person('bob'
)p2 = person('
alice')
p1.address
#=> earth
p2.address
#=> earth
由於python是動態語言,類屬性也是可以動態新增和修改的:
person.address = 'china
p1.address
#=> 'china'
p2.address
#=> 'china'
因為類屬性只有一份,所以,當person類的address改變時,所有例項訪問到的類屬性都改變了。
2、python中類屬性和例項屬性名字衝突怎麼辦
修改類屬性會導致所有例項訪問到的類屬性全部都受影響,但是,如果在例項變數上修改類屬性會發生什麼問題呢?
classperson(object):
address = '
earth
'def
__init__
(self, name):
self.name =name
p1 = person('
bob'
)p2 = person('
alice')
'person.address =
' +person.address
p1.address = '
china
'p1.address =
' +p1.address
'person.address =
' +person.address
'p2.address =
' + p2.address
結果如下:
person.address =earthp1.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'了:
delp1.address
p1.address
#=> earth
可見,千萬不要在例項上修改類屬性,它實際上並沒有修改類屬性,而是給例項繫結了一個例項屬性。
3、python中定義例項方法
一個例項的私有屬性就是以__開頭的屬性,無法被外部訪問,那這些屬性定義有什麼用?
雖然私有屬性無法從外部訪問,但是,從類的內部是可以訪問的。除了可以定義例項的屬性外,還可以定義例項的方法。
例項的方法就是在類中定義的函式,它的第一個引數永遠是 self,指向呼叫該方法的例項本身,其他引數和一個普通函式是完全一樣的:
classperson(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)
p1.get_grade()
p2.get_grade()
print p3.get_grade()
4、python中方法也是屬性
我們在 class 中定義的例項方法其實也是屬性,它實際上是一個函式物件:
classperson(object):
def__init__
(self, name, score):
self.name =name
self.score =score
defget_grade(self):
return'a
'p1 = person('
bob', 90)
p1.get_grade
#=> >
p1.get_grade()
#=> a
也就是說,p1.get_grade 返回的是一個函式物件,但這個函式是一個繫結到例項的函式,p1.get_grade() 才是方法呼叫。
因為方法也是一個屬性,所以,它也可以動態地新增到例項上,只是需要用 types.methodtype() 把一個函式變為一個方法:
importtypes
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)
p1.get_grade()
#=> a
p2 = person('
alice
', 65)
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的首字母縮寫 ,我們知道,物件導向的特點是繼承 多型和封裝。而封裝就...