1、一般用類自帶的__init__函式完成類變數的初始化工作,並且類函式的第乙個引數一般都是self,用來表示物件自身,類似於c++物件裡面的this指標。並且定義了__init__函式的類就必須按照這個函式引數的形式來構造物件。當然也有特殊的函式,比如說__new__,它的第乙個引數是cls,表示類本身,是因為這個函式的作用相當於是用來構造類,而不是物件的。
2、不像c++,變數必須都要包括在類定義裡面,每個類物件可以隨時新增變數,當然,這個變數也只屬於這個物件,其他物件引用是會出錯的。
3、定義私有變數,是在正常名字前面加上雙下劃線,就成了私有的,不像c++是通過關鍵字private來定義的。並且也不是說完全不能訪問,是因為直譯器把它解釋成了別的名字,例如student類的__name私有變數,直接通過__name是不能訪問的,但是用它解釋後的名字_student__name則是可以訪問的。
4、對於帶有前雙下劃線和後雙下劃線的變數,這些變數可以在外部訪問,但這些是特殊變數,自己定義的變數不要寫成這種形式。
5、前面帶有單下劃線的變數,也可以在外部訪問,但一般也把它們當做私有變數不要去訪問它。
6、使用dir(物件名)函式可以得到這個物件所屬型別的所有可用函式和變數
類的整合與派生
1、在派生類,只需要重寫基類的函式,函式宣告一致,就自動與基類同名函式互為虛函式,假定函式形參是基類型別,如果給乙個基類的實參,就呼叫基類的函式,如果給的是繼承類的物件,就呼叫繼承類的函式。當然如果繼承類沒有重寫函式,都會呼叫基類的函式。
2、如果類沒有直接的基類,就讓它繼承系統的object類,從這樣看,所有的類的基類都是object。
3、判斷某個變數是否是某個型別可用isinstance判斷,會返回true或false,並且在判斷類物件時,只要型別名是該物件的類或該類的基類,返回值都是true,用法為:
isinstance(變數名,型別名)
4、判斷某個物件的型別可用type()判斷,會直接返回型別名,用法為
type(物件名)
5、有了上面判斷物件的型別,也有判斷判斷物件中是否含有某屬性的方法,常用的方法有以下三個:
hasattr(物件名,屬性變數名)#判斷物件中是否含有某變數,這個方法在構造單例時非常有用
getattr(物件名,屬性變數,預設值)#獲取指定屬性的值,如果屬性不存在,就返回預設值
setattr(物件名,屬性變數,設定值)#設定指定屬性的值
高階特性
__slots__
1、類物件可以動態新增自己的屬性,如果要限制變數的名字,就可以使用這個屬性,講乙個元組賦給它,這樣就只能新增元組裡每個元素指定變數名
2、該屬性只對當前類起作用,如果繼承類沒使用該屬性,就不會繼承該特性,使用了就會繼承。
類自帶的特殊方法
__iter__
如果乙個類想被用於for ... in迴圈,類似list或tuple那樣,就必須實現乙個__iter__()方法,該方法返回乙個迭代物件,然後,python的for迴圈就會不斷呼叫該迭代物件的next()方法拿到迴圈的下乙個值,直到遇到stopiteration錯誤時退出迴圈。
我們以斐波那契數列為例,寫乙個fib類,可以作用於for迴圈:
classfib(object):def __init__(self):
self.a, self.b= 0, 1 #初始化兩個計數器a,b
def __iter__(self):return self #例項本身就是迭代物件,故返回自己
defnext(self):
self.a, self.b= self.b, self.a + self.b #計算下乙個值
if self.a > 100000: #退出迴圈的條件
raisestopiteration();return self.a #返回下乙個值
__getitem__
可以像列表那樣用索引來去除第幾個元素
__getattr__()
用於動態返回乙個屬性
type()
動態語言和靜態語言最大的不同,就是函式和類的定義,不是編譯時定義的,而是執行時動態建立的。
比方說我們要定義乙個hello的class,就寫乙個hello.py模組:
classhello(object):def hello(self, name='world'):print('hello, %s.' % name)
當python直譯器載入hello模組時,就會依次執行該模組的所有語句,執行結果就是動態建立出乙個hello的class物件,測試如下:
>>> from hello importhello>>> h =hello()>>>h.hello()
hello, world.>>> print(type(hello))
>>> print(type(h))
type()函式可以檢視乙個型別或變數的型別,hello是乙個class,它的型別就是type,而h是乙個例項,它的型別就是class hello。
我們說class的定義是執行時動態建立的,而建立class的方法就是使用type()函式。
type()函式既可以返回乙個物件的型別,又可以建立出新的型別,比如,我們可以通過type()函式建立出hello類,而無需通過class hello(object)...的定義:
>>> def fn(self, name='world'): #先定義函式
... print('hello, %s.' %name)
...>>> hello = type('hello', (object,), dict(hello=fn)) #建立hello
class
>>> h =hello()>>>h.hello()
hello, world.>>> print(type(hello))
>>> print(type(h))
要建立乙個class物件,type()函式依次傳入3個引數:
1. class的名稱;
2. 繼承的父類集合,注意python支援多重繼承,如果只有乙個父類,別忘了tuple的
單元素寫法;
3. class的方法名稱與函式繫結,這裡我們把函式fn 繫結到方法名hello上。
通過type()函式建立的類和直接寫class是完全一樣的,因為python直譯器遇到class定義時,僅僅是掃瞄一下class定義的語法,然後呼叫type()函式建立出class。
正常情況下,我們都用class ***...來定義類,但是,type()函式也允許我們動態建立出類來,也就是說,動態語言本身支援執行期動態建立類,這和靜態語言有非常大的不同,要在靜態語言執行期建立類,必須構造源**字串再呼叫編譯器,或者借助一些工具生成位元組碼實現,本質上都是動態編譯,會非常複雜。
metaclass
除了使用type()動態建立類以外,要控制類的建立行為,還可以使用metaclass。metaclass,直譯為元類,簡單的解釋就是:當我們定義了類以後,就可以根據這個類建立出例項,所以:先定義類,然後建立例項。
但是如果我們想建立出類呢?那就必須根據metaclass建立出類,所以:先定義metaclass,然後建立類。
連線起來就是:先定義metaclass,就可以建立類,最後建立例項。
所以,metaclass允許你建立類或者修改類。換句話說,你可以把類看成是metaclass建立出來的「例項」。
多重基類和虛擬基類
多重繼承 multiple inheritance,mi 虛基類虛基類使得從多個類 它們的基類相同 派生出的物件只繼承乙個基類物件。通過使用關鍵字virtual。例如,可以使worker被用作singer和waiter的虛基類 virtual和public的次序無關緊要 當基類是虛基類,派生類將包含...
python抽象基類理解
抽象基類它提供了介面,但是又沒有去把介面實現的類,需要由子類完成。感覺它就是老闆,只告訴你要完成專案a,你接到專案a後 繼承 你自己去把它完成。抽象基類特點 1.繼承類必須實現抽象基類的方法 2.抽象基類無法例項化 1.why 抽象基類?譬如要開發乙個專案,你要規定專案開發者要去完成某些介面,有些介...
python中建立類role 初識Python類
吐槽 學習物件導向就像你追乙個女神一樣,剛剛有點感覺了,過幾天又陷入絕望的感覺,很蛋疼。類的語法 classperson object print learning class test person test就是類person的例項化物件 例項化,就是以person類為模板,在記憶體裡開闢一塊空間...