python學(xué)習(xí)筆記,特做記錄沪斟,分享給大家,希望對大家有所幫助择吊。
類和實例
面向?qū)ο笞钪匾母拍罹褪穷悾–lass)和實例(Instance),必須牢記類是抽象的模板槽奕,比如Student類几睛,而實例是根據(jù)類創(chuàng)建出來的一個個具體的“對象”,每個對象都擁有相同的方法所森,但各自的數(shù)據(jù)可能不同夯接。
仍以Student類為例,在Python中盔几,定義類是通過class關(guān)鍵字:
class Student(object):
pass
class后面緊接著是類名,即Student肝匆,類名通常是大寫開頭的單詞顺献,緊接著是(object)旗国,表示該類是從哪個類繼承下來的,繼承的概念我們后面再講能曾,通常,如果沒有合適的繼承類寿冕,就使用object類,這是所有類最終都會繼承的類藻茂。
定義好了Student類玫恳,就可以根據(jù)Student類創(chuàng)建出Student的實例,創(chuàng)建實例是通過類名+()實現(xiàn)的:
>>> bart = Student()
>>> bart
<__main__.Student object at 0x10a67a590>
>>> Student
<class '__main__.Student'>
可以看到京办,變量bart指向的就是一個Student的實例,后面的0x10a67a590是內(nèi)存地址不恭,每個object的地址都不一樣换吧,而Student本身則是一個類。
可以自由地給一個實例變量綁定屬性筋遭,比如,給實例bart綁定一個name屬性:
>>> bart.name = 'Bart Simpson'
>>> bart.name
'Bart Simpson'
由于類可以起到模板的作用编饺,因此透且,可以在創(chuàng)建實例的時候豁鲤,把一些我們認為必須綁定的屬性強制填寫進去。通過定義一個特殊的init方法锅论,在創(chuàng)建實例的時候楣号,就把name怒坯,score等屬性綁上去:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
注意:特殊方法“init”前后分別有兩個下劃線L拊场f揖!!
注意到init方法的第一個參數(shù)永遠是self,表示創(chuàng)建的實例本身蝶锋,因此,在init方法內(nèi)部慌闭,就可以把各種屬性綁定到self驴剔,因為self就指向創(chuàng)建的實例本身丧失。
有了init方法惜互,在創(chuàng)建實例的時候,就不能傳入空的參數(shù)了训堆,必須傳入與init方法匹配的參數(shù)坑鱼,但self不需要傳,Python解釋器自己會把實例變量傳進去:
>>> bart = Student('Bart Simpson', 59)
>>> bart.name
'Bart Simpson'
>>> bart.score
59
和普通的函數(shù)相比呼股,在類中定義的函數(shù)只有一點不同画恰,就是第一個參數(shù)永遠是實例變量self,并且阐枣,調(diào)用時奄抽,不用傳遞該參數(shù)甩鳄。除此之外,類的方法和普通函數(shù)沒有什么區(qū)別档泽,所以揖赴,你仍然可以用默認參數(shù)、可變參數(shù)燥滑、關(guān)鍵字參數(shù)和命名關(guān)鍵字參數(shù)。
數(shù)據(jù)封裝
面向?qū)ο缶幊痰囊粋€重要特點就是數(shù)據(jù)封裝赃蛛。在上面的Student類中搀菩,每個實例就擁有各自的name和score這些數(shù)據(jù)。我們可以通過函數(shù)來訪問這些數(shù)據(jù)肪跋,比如打印一個學(xué)生的成績:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
bart = Student('Bart Simpson', 59)
print bart.name
print bart.score
def print_score(std):
print '%s: %s' % (std.name, std.score)
print_score(bart)
運行結(jié)果:
Bart Simpson
59
Bart Simpson: 59
Process finished with exit code 0
但是,既然Student實例本身就擁有這些數(shù)據(jù)谜洽,要訪問這些數(shù)據(jù)易桃,就沒有必要從外面的函數(shù)去訪問锌俱,可以直接在Student類的內(nèi)部定義訪問數(shù)據(jù)的函數(shù),這樣贸宏,就把“數(shù)據(jù)”給封裝起來了。這些封裝數(shù)據(jù)的函數(shù)是和Student類本身是關(guān)聯(lián)起來的诫龙,我們稱之為類的方法:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name, self.score))
要定義一個方法鲫咽,除了第一個參數(shù)是self外谷异,其他和普通函數(shù)一樣锦聊。要調(diào)用一個方法,只需要在實例變量上直接調(diào)用孔庭,除了self不用傳遞,其他參數(shù)正常傳入:
bart.print_score()
運行結(jié)果:
Bart Simpson
59
Bart Simpson: 59
Process finished with exit code 0
這樣一來怎抛,我們從外部看Student類芽淡,就只需要知道,創(chuàng)建實例需要給出name和score吐绵,而如何打印己单,都是在Student類的內(nèi)部定義的唉窃,這些數(shù)據(jù)和邏輯被“封裝”起來了纹份,調(diào)用很容易廷痘,但卻不用知道內(nèi)部實現(xiàn)的細節(jié)蔓涧。
封裝的另一個好處是可以給Student類增加新的方法笋额,比如get_grade:
class Student(object):
...
def get_grade(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
同樣的兄猩,get_grade方法可以直接在實例變量上調(diào)用,不需要知道內(nèi)部實現(xiàn)細節(jié):
# -*- coding: utf-8 -*-
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print '%s: %s' % (self.name, self.score)
def get_grade(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
lisa = Student('Lisa', 99)
bart = Student('Bart', 59)
print(lisa.name, lisa.get_grade())
print(bart.name, bart.get_grade())
運行結(jié)果:
('Lisa', 'A')
('Bart', 'C')
Process finished with exit code 0