在面向?qū)ο蟮恼Z言中,類是最重要的一環(huán),python自然擁有類這個機(jī)制。python的類機(jī)制,與C++,java的區(qū)別不是很大,類的大多數(shù)的重要特性都被沿用了,一樣可以多態(tài),抽象,封裝;
在介紹類之前,首先介紹下一下關(guān)于python作用域的規(guī)則;
1.命名空間:
是從命名到對象的映射。當(dāng)前命名空間主要是通過 Python 字典實(shí)現(xiàn)的,不過通常不關(guān)心具體的實(shí)現(xiàn)方式(除非出于性能考慮);
以下有一些命名空間的例子:
內(nèi)置命名(像 abs() 這樣的函數(shù),以及內(nèi)置異常名)集,模塊中的全局命名,函數(shù)調(diào)用中的局部命名。某種意義上講對象的屬性集也是一個命名空間。
關(guān)于命名空間需要了解的一件很重要的事就是不同命名空間中的命名沒有任何聯(lián)系,例如兩個不同的模塊可能都會定義一個名為 maximize 的函數(shù)而不會發(fā)生混淆--用戶必須以模塊名為前綴來引用它們。比如:math中有sin函數(shù),可以通過math.sin調(diào)用;
2.作用域:
就是一個 Python 程序可以直接訪問命名空間的正文區(qū)域。 這里的 直接訪問 意思是一個對名稱的錯誤引用會嘗試在命名空間內(nèi)查找。
一個例子:
def scope_test(): def do_local(): spam = "local spam"#局部變量 def do_nonlocal(): nonlocal spam spam = "nonlocal spam"#域變量,在整個函數(shù)域有效。 def do_global(): global spam spam = "global spam"# spam = "test spam"#全局變量,此處在函數(shù)域外有效; do_local() PRint("After local assignment:", spam) do_nonlocal() print("After nonlocal assignment:", spam) do_global() print("After global assignment:", spam)scope_test()print("In global scope:", spam)#全局變量作用域##輸出:After local assignment: test spamAfter nonlocal assignment: nonlocal spamAfter global assignment: nonlocal spamIn global scope: global spam類定義形式:
class className(superClass): <statement 1> ..... <statement N>類定義就像函數(shù)定義一樣,要先執(zhí)行才能生效。習(xí)慣上statement語句是函數(shù)定義,不過其他語句也可以。
進(jìn)入類定義部分后會創(chuàng)建出一個新的命名空間,作為局部作用域,因此所有的賦值成為這個新命名空間的局部變量,特別時函數(shù)定義在此處綁定了新的名字
類定義完成時,就創(chuàng)建了一個類對象。也就是類名;
類對象支持兩種操作:屬性應(yīng)用和實(shí)例化.
屬性應(yīng)用使用:類名.屬性;例如類定義如下:
class Myclass: "一個簡單的類用于屬性介紹" num=123 def fun(self): return 'hello world'那么我可以Myclass.num和Myclass.fun是有效的屬性引用;分別返回一個整數(shù),和一個方法對象;
類定義的實(shí)例化:類的實(shí)例話使用函數(shù)符號 :類名();
例如:x=Myclass()
以上創(chuàng)建了一個新的類的實(shí)例,并將該對象賦值給了變量x。此去沒有初始化;
很多類都傾向于將對象創(chuàng)建為有初始狀態(tài)的。因此類可能會定義一個名為 init() 的特殊方法,像下面這樣:
def __init__(self): self.data = []類定義了 init() 方法的話,類的實(shí)例化操作會自動為新創(chuàng)建的類實(shí)例調(diào)用__init__() 方法。所以在下例中,可以這樣創(chuàng)建一個新的實(shí)例:
x = MyClass()
當(dāng) 然 , 出 于 彈 性 的 需 要 , init() 方 法 可 以 有 參 數(shù) 。 事 實(shí) 上 , 參 數(shù) 通 過__init__() 傳遞到類的實(shí)例化操作上。
實(shí)例對象就是用來操作類的屬性引用;有兩種引用:數(shù)據(jù)和方法
數(shù)據(jù):和java中的成員類似,其實(shí)就是變量;和局部變量一樣,數(shù)據(jù)屬性不需要聲明,第一次使用他們時就會生成;
比如:
x=Myclass()#Myclass類中沒有聲明,可以直接使用;x.counter=1方法:方法是屬于一個類的函數(shù),方法引用為:x.fun();
也可以將方法引用賦值給變量這與函數(shù)賦值是一樣的;
xf=x.fun()#注意self參數(shù),是對象實(shí)例化作為第一個參數(shù)傳給變量的,不需要顯示調(diào)用;
1實(shí)例屬性介紹:
給實(shí)例綁定屬性的方法是通過實(shí)例變量,或者通過self變量:
class Student(object): def __init__(self, name): self.name = name s = Student('peace') s.score =40name和score都是實(shí)例屬性;
2類屬性:
可以直接在class中定義屬性,這種屬性是類屬性,歸類所有:
class student: name="peace"name就是類屬性,類的所有實(shí)例都可以訪問到,并且是指向同一個對象;
沒有繼承就沒有類,而python類的定義如下:
class className(superClass): <statement 1> ..... <statement N>##其中className就是superclass的派生類。實(shí)例介紹:
class Animal(object): def run(self): print('Animal is running...')class Dog(Animal): passclass Cat(Animal): pass對于dog與cat來說,Animal就是它的父類。
如果在子類中找不到請求調(diào)用的屬性,就搜索基類。如果基類是由別的類派生而來,這個規(guī)則會遞歸的應(yīng)用上去?,F(xiàn)在Dog和Cat方法都可以調(diào)用run方法了。
也可以增加方法:
class Dog(Animal): def see(self): print('see a dog')派生類可以覆蓋其基類的方法。因?yàn)榉椒ㄕ{(diào)用同一個對象中的其它方法時沒有特權(quán),基類的方法調(diào)用同一個基類的方法時,可能實(shí)際上最終調(diào)用了派生類中的覆蓋方
法。
class Dog(Animal): def run(self): print('Dog is running...')class Cat(Animal): def run(self): print('Cat is running...')多態(tài)的好處:
def run_twice(animal): animal.run() animal.run()##測試多態(tài):>>> run_twice(Animal()) Animal is running... Animal is running...>>> run_twice(Dog()) Dog is running...Dog is running...對于一個變量,我們只需要知道它是Animal類型,無需確切地知道它的子類型,就可以放心地調(diào)用run()方法,而具體調(diào)用的run()方法是作用在Animal、Dog、Cat還是Tortoise對象上,由運(yùn)行時該對象的確切類型決定,這就是多態(tài)真正的威力:調(diào)用方只管調(diào)用,不管細(xì)節(jié),而當(dāng)我們新增一種Animal的子類時,只要確保run()方法編寫正確,不用管原來的代碼是如何調(diào)用的。這就是著名的“開閉”原則:
對擴(kuò)展開放:允許新增Animal子類;
對修改封閉:不需要修改依賴Animal類型的run_twice()等函數(shù)。
5.派生類的的實(shí)例化與普通類沒有什么差別;
Python 有兩個用于繼承的函數(shù):
? 函數(shù) isinstance() 用于檢查實(shí)例類型: isinstance(obj, int) 只有在obj.__class__ 是 int 或其它從 int 繼承的類型 ? 函數(shù) issubclass() 用于檢查類繼承: issubclass(bool, int) 為 True,因?yàn)?bool 是 int 的子類。但是, issubclass(unicode, str) 是 Fals ,因?yàn)?unicode 不是 str 的子類(它們只是共享一個通用祖先類 basestring)。python支持多重繼承:
class className(superClass1,superClass1,superClass2.....): <statement 1> ..... <statement N>##其中className就是superClass1,superClass1,superClass2.....的派生類。只需要在數(shù)據(jù)或者方法前面加上_兩個下劃線就行,例如spam。python獨(dú)特的命名編碼會將spam替代為 classname__spam
這樣在外面就不能正常的 按照:類名.__spam進(jìn)行調(diào)用了。但是寫全的話替代為 類名. _classname__spam還是可以的,這時python的缺陷
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í)例變量.name和實(shí)例變量.score了
可以自己定義異常的派生類,通過rasie進(jìn)行拋出;
有兩種拋出方式:
1.raise Classname()定義的派生類;
2.raise 實(shí)例;由異常類實(shí)例話而來;
演示如下:
class B(Exception): passclass C(B): passclass D(C): passfor cls in [B, C, D]: try: raise cls() except D: print("D") except C: print("C") except B: print("B")要 注 意 的 是 如 果 異 常 子 句 的 順 序 顛 倒 過 來 ( execpt B 在 最 前 ) , 它 就 會 打 印B,B,B--第一個匹配的異常被觸發(fā)。
python3入門之類
python3入門之函數(shù)
python3入門之循環(huán)
python3之if語句
python3入門之賦值語句介紹
python3入門之print,import,input介紹
python3入門之set
python3入門之字典
python3入門之字符串
python3入門之列表和元組
python3入門之軟件安裝
python3爬蟲之入門和正則表達(dá)式
新聞熱點(diǎn)
疑難解答