保護對象的屬性 如果有一個對象,當需要對其進行修改屬性時,有2鐘方法: 對象名.屬性名 = 數據 >直接修改 對象名.方法名() >間接修改 為了更好的保存屬性的安全,即不能隨意修改,一般的處理方式為: 將屬性定義為私有屬性 添加一個可以調用的方法,供調用 運行結果為: 修改代碼: 運行結果: 總結 ...
保護對象的屬性
如果有一個對象,當需要對其進行修改屬性時,有2鐘方法:
- 對象名.屬性名 = 數據 ---->直接修改
- 對象名.方法名() ---->間接修改
為了更好的保存屬性的安全,即不能隨意修改,一般的處理方式為:
- 將屬性定義為私有屬性
- 添加一個可以調用的方法,供調用
11 class Person(object): 12 def __init__(self,name): 13 self.__name = name 14 def getName(self): 15 return self.__name 16 def setName(self,newName): 17 if len(newName)>=5: 18 self.__name = newName 19 else: 20 print('error:名字的長度要大於或者等於5') 21 22 xiaoming = Person('XIAOYAFEI') 23 print(xiaoming.__name)
運行結果為:
Traceback (most recent call last): File "test.py", line 23, in <module> print(xiaoming.__name) AttributeError: 'Person' object has no attribute '__name'
修改代碼:
11 class Person(object): 12 def __init__(self,name): 13 self.__name = name 14 def getName(self): 15 return self.__name 16 def setName(self,newName): 17 if len(newName)>=5: 18 self.__name = newName 19 else: 20 print('error:名字的長度要大於或者等於5') 21 22 xiaoming = Person('XIAOYAFEI') 23 24 xiaoming.setName("wang") 25 print(xiaoming.getName()) 26 27 xiaoming.setName('lisisi') 28 print(xiaoming.getName())
運行結果:
error:名字的長度要大於或者等於5
XIAOYAFEI
lisisi
總結:
- python中沒有像C++中public和private這些關鍵字來區別公有屬性和私有屬性
- 它是以屬性命名方式來區分,如果在屬性名前面加了2個下劃線'__',則表示該屬性是私有屬性,否則為公有屬性(方法也是一樣,方法名前面加了2個下劃線的話表示該方法是私有的,否則為公有的)
__del__()方法
創建對象後,python解釋器預設調用__init__()方法;
當刪除一個對象時,python解釋器也會預設調用一個方法,這個方法為__del__()方法
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-08 15:28:14 6 7 # File Name: test2.py 8 # Description: 9 10 """ 11 import time 12 class Animal(): 13 #初始化方法 14 #創建為對象後會自動被調用 15 def __init__(self,name): 16 print('???????__init__方法被調用???????') 17 self.__name = name 18 19 #析構方法 20 #當對象被刪除時,會自動被調用 21 def __del__(self): 22 print('__del__方法被調用') 23 print('%s對象馬上被幹掉了......'%self.__name) 24 25 #創建對象 26 dog = Animal('嗨皮') 27 #刪除對象 28 del dog 29 30 cat = Animal('波斯貓') 31 cat2 = cat 32 cat3 = cat 33 34 print('馬上刪除cat對象') 35 del cat 36 print('馬上刪除cat1對象') 37 del cat2 38 print('馬上刪除cat2對象') 39 del cat3 40 41 print('程式在2秒鐘後結束') 42 time.sleep(2)
運行結果如下:
———————__init__方法被調用——————— __del__方法被調用 嗨皮對象馬上被幹掉了...... ———————__init__方法被調用——————— 馬上刪除cat對象 馬上刪除cat1對象 馬上刪除cat2對象 __del__方法被調用 波斯貓對象馬上被幹掉了...... 程式在2秒鐘後結束
總結:
- 當有1個變數保存了對象的引用時,此對象的引用計數就會加1
- 當使用del刪除變數指向的對象時,如果對象的引用計數不為1,比如3,那麼此時只會讓這個引用計數減1,即變為2,當再次調用del時,變為1,如果再調用1次del,此時會真的把對象進行刪除
繼承
在程式中,繼承描述的是事物之間的所屬關係,例如貓和狗都屬於動物,程式中便可以描述為狗和貓繼承自動物;同理,波斯貓和巴釐貓都繼承自貓,而沙皮狗和斑點狗都繼承自狗
繼承示例
#!/usr/bin/python #coding=utf8 """ # Author: xiaoyafei # Created Time : 2018-04-04 11:35:02 # File Name: 03-單繼承.py # Description: """ #定義一個父類 class Cat(): def __init__(self,name,color="白色"): self.name = name self.color = color def run(self): print('%s------在跑'%self.name) #定義一個子類,來繼承Cat類 class Bosi(Cat): def __str__(self): return self.name def setNewName(self,newName): self.name = newName def eat(self): print("%s------在吃"%self.name) bs = Bosi("lipeng") bs.run() bs.setNewName("小明") print(bs)
運行結果為:
lipeng------在跑
小明
說明:
- 雖然子類沒有定義__init__方法,但是父類有,所以在子類繼承父類的時候這個方法就被繼承了,所以只要創建Bosi對象,就預設執行了那個繼承過來的父類的__init__方法
總結:
- 子類在繼承的時候,在定義類時,小括弧()中為父類的名字
- 父類的屬性、方法,會被繼承給子類
註意點
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-08 15:45:07 6 7 # File Name: 04-單繼承-註意點.py 8 # Description: 9 10 """ 11 class Animal(): 12 def __init__(self,name='動物',color='白色'): 13 self.__name = name 14 self.color = color 15 def __test(self): 16 print(self.__name) 17 print(self.color) 18 def test(self): 19 print(self.__name) 20 print(self.color) 21 22 class Dog(Animal): 23 def dogTest1(self): 24 #print(self.__name) 25 print(self.color) 26 def dogTest2(self): 27 #self.__test() 28 self.test() 29 30 A = Animal() 31 #print(A.__name) #程式出現異常,不能直接訪問私有屬性 32 print(A.color) 33 #A.__test() #程式出現異常,不能直接訪問私有方法 34 A.test() 35 36 print('----------------------------華麗的分割線----------------------------------') 37 D = Dog(name = '小花狗',color = '黃色') 38 D.dogTest1() 39 D.dogTest2()
- 私有的屬性,不能通過對象直接訪問,但是可以通過方法訪問
- 私有的方法,不能通過對象直接訪問
- 私有的屬性、方法,不會被子類繼承,也不能給訪問
- 一般情況下,私有的屬性、方法都是不對外公佈的,往往來做內部的事情,起到安全的作用
多繼承
所謂多繼承,即子類有多個父類,並且具有它們的特征
python中多繼承的格式如下:
14 class a(): 15 def printA(self): 16 print('-aaaaaaaaaaaaa') 17 18 class b(): 19 def printB(self): 20 print('------------b') 21 22 23 class c(a,b): 24 def printC(self): 25 print('-cccccccccccccccccc') 26 27 c = c() 28 c.printA() 29 c.printB() 30 c.printC()
運行結果如下:
-aaaaaaaaaaaaa ------------b -cccccccccccccccccc
說明:
- python中是可以多繼承的
- 父類中的方法、屬性,子類會繼承
多繼承-註意點
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-04 14:29:20 6 7 # File Name: 06-多繼承註意點.py 8 # Description: 9 在多個父類中擁有相同的方法應該調用哪一個??? 10 11 可以使用__mro__方法去查看調用順序 12 """ 13 14 class A(): 15 def printA(self): 16 print('aaaaaaaaaaaaaaaaaa') 17 class B(): 18 def printA(self): 19 print('bbbbbbbbbbbbbbbbb') 20 21 class S(A,B): 22 def printS(self): 23 print('SSSSSSSSSSSSSSSSSS') 24 25 zi = S() 26 zi.printS() 27 zi. printA() 28 print(S.__mro__) #可以查看C類的對象搜索方法時的先後順序
運行結果:
SSSSSSSSSSSSSSSSSS aaaaaaaaaaaaaaaaaa (<class '__main__.S'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
重寫父類方法和調用父類方法
重寫父類方法
所謂重寫,就是子類中,有一個和父類相同名字的方法,在子類中的方法會覆蓋掉父類中同名的方法
13 class Cat(): 14 def sayHello(self): 15 print('Hello----1') 16 17 class Bosi(Cat): 18 def sayHello(self): 19 print('Hello----4') 20 bosi = Bosi() 21 bosi.sayHello()
運行結果如下:
Hello----4
調用父類方法
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-08 17:28:14 6 7 # File Name: 08-調用父類的方法-1.py 8 # Description: 9 10 """ 11 class Cat(): 12 def __init__(self,name): 13 self.name = name 14 self.color = 'yellow' 15 16 class Bosi(Cat): 17 def __init__(self,name): 18 super().__init__(name) 19 20 def getName(self): 21 return self.name 22 23 bosi = Bosi('波斯貓') 24 print(bosi.name) 25 print(bosi.color)
運行結果如下:
波斯貓
yellow
super()不是父類,而是繼承順序的下一個類
在多重繼承是會涉及到繼承順序,super()相當於返回繼承順序的下一個類,而不是父類
多態
多態的概念是應用於Java和c#這一類強語言中,而python崇尚"鴨子類型"
所謂多態:定義時的類型和運行時的類型不一樣,此時就形成了多態
python鴨子類型代碼:
12 class F1(object): 13 def show(self): 14 print('F1.show') 15 class S1(F1): 16 def show(self): 17 print('S1.show') 18 class S2(F1): 19 def show(self): 20 print('S2.show') 21 22 def Func(obj): 23 print(obj.show()) 24 25 s1_obj = S1() 26 Func(s1_obj) 27 28 s2_obj = S2() 29 Func(s2_obj)