class Point(object): def __init__(self,name,score): self.__name = name self.__score = score def print_data(self): print('name:%s score:%s' % (self.__name,self.__score)) def get_grade(self): if self.__score >= 90: return 'A' elif self.__score >= 60 and self.__score < 90: return 'B' else: return 'C' def get_name(self): return self.__name def get_score(self): return self.__score def set_name(self,name): self.__name = name def set_score(self,score): self.__score = score def run(self): print('Point') p1 = Point('傻狗1',30) p1.print_data() print(p1.get_grade()) #print(p1.__name)#沒法從外部訪問實例變量.__name和實例變量.__score,確保了外部代碼不能隨意修改對象內部的狀態 print(p1.get_name())#外部代碼要獲取name和score,給Ponit類增長get_name和get_score p1.set_score(300)#容許外部代碼修改score print(p1.get_score()) #變量名相似__xxx__的,也就是以雙下劃線開頭,而且以雙下劃線結尾的,是特殊變量,特殊變量是能夠直接訪問的,不是private變量,因此,不能用__name__、__score__這樣的變量名 #_name,這樣的實例變量外部是能夠訪問的,可是,按照約定俗成的規定,當你看到這樣的變量時,意思就是,「雖然我能夠被訪問,可是,請把我視爲私有變量,不要隨意訪問」 class PointExtend(Point): def run(self):#能夠對子類增長一些方法 print('PointExtend') p2 = PointExtend('子類1',30) print(p2.get_grade()) #p1.run() #p2.run()#當子類和父類都存在相同的run()方法時,咱們說,子類的run()覆蓋了父類的run(),在代碼運行的時候,老是會調用子類的run() #理解什麼是多態,咱們首先要對數據類型再做一點說明。當咱們定義一個class的時候,咱們實際上就定義了一種數據類型。咱們定義的數據類型和Python自帶的數據類型,好比str、list、dict沒什麼兩樣 #a = list() # a是list類型 #b = Point() # b是Point類型 #c = PointExtend() # c是PointExtend類型 #isinstance(a, list) True #isinstance(b, Point) True #isinstance(c, PointExtend) True #對於一個變量,咱們只須要知道它是Point類型,無需確切地知道它的子類型,就能夠放心地調用run()方法 def run_twice(point): point.run() run_twice(p1)#Point run_twice(p2)#PointExtend #新增一種Point的子類時,只要確保run()方法編寫正確,不用管原來的代碼是如何調用的。這就是著名的「開閉」原則 #對擴展開放:容許新增Point子類; #對修改封閉:不須要修改依賴Point類型的run_twice()等函數。 #對於靜態語言(例如Java)來講,若是須要傳入Point類型,則傳入的對象必須是Point類型或者它的子類,不然,將沒法調用run()方法。 #對於Python這樣的動態語言來講,則不必定須要傳入Point類型。咱們只須要保證傳入的對象有一個run()方法就能夠了 class NoPoint(object): def run(self): print('NoPoint') p3 = NoPoint() run_twice(p3)#NoPoint #這就是動態語言的「鴨子類型」,它並不要求嚴格的繼承體系,一個對象只要「看起來像鴨子,走起路來像鴨子」,那它就能夠被看作是鴨子