繼承和多態
繼承的概念:
在現實生活中,繼承一般指的是子女繼承父輩的財產。那麼在程序中,繼承描述的是事物之間的所屬關係,例如貓和狗都屬於動物,程序中可以描述爲貓和狗都繼承自動物。同理,波斯貓和家貓都繼承自貓。而斑點狗,泰迪都繼承之狗。程序中當我們定義一個class的時候,可以從某個現有的class繼承,新的class稱之爲子類(Subclass),而被繼承的class稱之爲基類、父類或超類。子類繼承了其父類的所有屬性和方法,同時還可以定義自己的屬性和方法。
多繼承:
Python中多繼承的語法格式如下:
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
需要注意圓括號中父類的順序,如果繼承的父類中有相同的方法名,而在子類中使用時未指定,python 將從左至右查找父類中是否包含方法。
重寫:
class Animal():
def __init__(self,name,food):
self.name = name
self.food = food
def eat(self):
print('%s喜歡喫%s'%(self.name,self.food))
def shout(self):
print(self.name,"喵喵")
#編寫一個Dog類繼承Animal
class Dog(Animal):
def __init__(self,name,food):
super().__init__(self,name,food)
def shout(self):#重寫父類的shout方法,喵喵叫不是Dog的叫聲
print(self.name,"汪汪叫")
#編寫一個Cat類繼承Animal
class Cat(Animal):
def __init__(self,name,food):
super().__init__(name,food)
#對於Dog和Cat來說,Animal是它們的父類,而Dog和Cat是Animal的子類
#子類獲得了父類全部的功能,自動擁有了父類的eat()方法
dog1 = Dog('小狗','骨頭')
dog1.shout()
類屬性和實例屬性:
屬性:儘量把需要用戶傳入的屬性作爲實例屬性,而把同類都一樣的屬性作爲類屬性。實例屬性在每創造一個類是都會初始化一遍,不同的實例的實例屬性可能不同,不同實例的類屬性都相同。
1:實例屬性:
在__init__(self,…)中初始化
內部調用時都需要加上self.
外部調用時用“對象名.屬性名”調用
2:類屬性:
在__init__()裏初始化
在內部用classname.類屬性名調用
外部既可以用classname.類屬性名又可以用instancename.類屬性名來調用
3:私有屬性:
1:雙下劃線__開頭:外部不可通過“對象名.屬性名”來訪問或者更改實際將其轉化爲了“_類名__屬性名”
單下劃線、雙下劃線、頭尾雙下劃線說明:
__foo__: 定義的是特殊方法,類似 __init__() 之類的。
_foo: 以單下劃線開頭的表示的是 protected 類型的變量,即保護類型只能允許其本身與子類進行訪問(創建的實例可以訪問),不能用於 from module import *
__foo: 雙下劃線的表示的是私有類型(private)的變量, 只能是允許這個類本身進行訪問了。
訪問權限
訪問限制—私有屬性:
私有類屬性
私有對象屬性
爲了保護屬性不被隨意修改和訪問,可以將屬性定義爲私有屬性。
如果要讓內部屬性不被外部訪問,可以把屬性的名稱前加上兩個下劃線__,在Python中,實例變量名如果以__開頭,就變成了一個私有變量(private),只有內部可以訪問,外部不能訪問.
訪問限制注意事項:
1.設置爲私有屬性不能直接通過對象訪問屬性,但是可以通過“實例化對象名._類名__屬性名”直接進行訪問。但是不建議這樣操作.不同版本的Python解釋器可能會把“__屬性名”改成不同的變量名。總的來說就是,Python本身沒有任何機制阻止你幹壞事,一切全靠自覺。
2.通過“對象名.__屬性名”直接修改私有屬性。
表面上看好像修改了其實並沒有,因爲Python解釋器已經將對象內部的屬性名解釋成“_類名__屬性名”。如果在外部修改相當於另外聲明一個屬性。
能直接修改嗎?類屬性可以直接修改通過類名._類名__屬性名=(可通過類方法定義後面說明)
類方法與靜態方法:
1:普通方法:
def fun_name(self,…):
pass
外部用實例調用
2:靜態方法:通過裝飾器 @staticmethod 裝飾
不能訪問實例屬性
參數不能傳入self
與類相關但是不依賴類與實例的方法
3:類方法:@classmethod
不能訪問實例屬性
參數必須傳入cls
必須傳入cls參數(即代表了此類對象-----區別------self代表實例對象),並且用此來調用類屬性:cls.類屬性名
靜態方法與類方法都可以通過類或者實例來調用。其兩個的特點都是不能夠調用實例屬性
靜態方法不需要接收參數,使用類名.類屬性