原創:叫我詹躲躲
來源:掘金
連接:python面型對象編程進階(繼承、多態、私有化、異常捕獲、類屬性和類方法)
致謝:感謝求知教育提供的視頻教程python
## 封裝,繼承和多態
## 1.封裝 1、知足把內容封裝到某個地方,另外一個地方去調用封裝的內容 2、使用初始化構造方法,或者使用self獲取封裝的內容 ## 2.繼承 子類繼承父類的屬性和內容 複製代碼
class Animal:
def eat(self): print('吃飯了') pass def drink(self): print('喝水了') pass class Dog(Animal): def wwj(self): ## 子類獨有的實現 print('小狗汪汪叫') pass class Cat(Animal): def mmj(self): ## 子類獨有的實現 print('小貓喵喵叫') pass d1 = Dog() d1.eat() d2 = Cat() d2.eat() ## 總結:因此對於面向對象的繼承來講,能夠極大的提高效率,減小重複代碼 複製代碼
class Shenxian:
def fly(self): print('神仙會飛') pass class Monkey: def chitao(self): print('猴子喜歡吃桃') pass class Sunwukong(Shenxian,Monkey): pass swk = Sunwukong() swk.fly() swk.chitao() 複製代碼
## 多個父類存在相同的方法,該調用哪個
class D(object): def eat(self): print('D.eat') pass class C(object): def eat(self): print('C.eat') pass class B(D): pass class A(B,C): pass a = A() a.eat print(A.__mro__) ##顯示類的繼承順序 <class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class 'object'> ## 執行順序應該是 去A裏面查找,找第一個父類,A中沒有的話,去B中查找,,B類中沒有,C類中沒有,去D類中查找; 複製代碼
class Grandfather():
def eat(self): print('吃的方法') pass pass class Father(Grandfather): pass class Son(Father): pass son = Son() print(Son.__mro__) ## <class '__main__.Son'>, ## <class '__main__.Father'>, ## <class '__main__.Grandfather'>, ## <class 'object'> 複製代碼
class Grandfather():
def eat(self): print('吃的方法') pass pass class Father(Grandfather): ## 覆蓋了父類的方法 def eat(self): print('爸爸常常吃海鮮') pass class Son(Father): pass son = Son() print(Son.__mro__) ## 定義跟父類相同的方法,能夠實現覆蓋和重寫父類的方法 複製代碼
class Grandfather():
def __init__(self,name): self.name = name pass def eat(self): print('吃的方法') pass pass class Father(Grandfather): def __init__(self): pass ## 覆蓋了父類的方法 def eat(self): print('爸爸常常吃海鮮') pass class Son(Father): pass son = Son() print(Son.__mro__) 複製代碼
class Father:
def __init__(self,name): self.name = name pass ## 覆蓋了父類的方法 def eat(self): print('爸爸常常吃海鮮') pass class Son(Father): def __init__(self,name): Father.__init__(self,name) ##調用父類的方法,能夠具有name屬性 ## 或者 ## super.__init__(name) ##也能夠這樣寫 self.age = 90 ## 添加新的實例方法 self.sex = '男' pass pass son = Son('hello') 複製代碼
class Father:
def __init__(self,name): self.name = name pass ## 覆蓋了父類的方法 def eat(self): print('父類的吃方法') pass class Son(Father): def __init__(self,name): Father.__init__(self,name) ##調用父類的方法,能夠具有name屬性 ## 或者 ## super.__init__(name) ##也能夠這樣寫 self.age = 90 ## 添加新的實例方法 self.sex = '男' pass pass def __str__(self): print('{}'.format(self.name)) pass def eat(self): super().eat() ##調用父類的方法 print('子類的吃方法') pass son = Son('詹躲躲') son.eat() ## 父類的吃方法 ## 子類的吃方法 複製代碼
同一種行爲,對於不一樣子類【對象】有不一樣的實現方式web
「1.繼承:發生在父類和子類之間數據庫
2.重寫:子類重寫父類的方法編程
3.1 案例演示編輯器
class Animal:
## 基本類 def say(self): print('動物類') pass pass class Duck(Animal): ## 子類 派生類 def say(self): print('鴨子類') pass pass class Dog(Animal): ## 子類 派生類 def say(self): print('小狗類') pass pass ## duck1 = Duck() ## duck1.say() ## dog = Dog() ## dog.say() def commonIvoke(obj): ## 統一調用 obj.say() ## 循環統一調用 listObj = [Duck(),Dog()] for item in listObj: commonIvoke(item) ## 在定義時的類型跟調用時不同的時候,稱爲多態。 複製代碼
1.增長程序的靈活性ide
2.增長程序的擴展性函數
## 類屬性:就是類對象擁有的屬性,它被全部類對象的實例對象所共有,類對象和實例對象能夠訪問。
## 實例屬性:實例對象所擁有的屬性,只能經過實例對象訪問。 class Student: ## 類屬性 name = '叫我詹躲躲' def __init__(self,age): self.age = age pass pass lm = Student(18) ## 經過實例對象去訪問類屬性 print(lm.name) print(lm.age) ## 經過類對象去訪問 print(Student.name) print(Student.age) ## 總結 ## 類屬性:類對象和實例對象均可以訪問 ## 實例屬性:只能由實例屬性訪問 ## 全部的實例對象指向同一類對象 ## 實例對象去修改類屬性 不能修改 ## 類對象能夠修改類屬性 能夠修改 複製代碼
## 裝飾器@classmethod
class Person: country = 'china' ## 類方法 用classmethod修飾 @classmethod def get_country(cls): return cls.country ## 訪問類屬性 pass @classmethod def change_country(cls): cls.country = 'America' pass ## 經過類對象去引用 print(Person.get_country()) print(Person.change_country()) print(Person.get_country()) 複製代碼
class Person:
country = 'china' ## 類方法 用classmethod修飾 @classmethod def get_country(cls): return cls.country ## 訪問類屬性 pass @classmethod def change_country(cls): cls.country = 'America' pass @staticmethod def get_data(): return Person.country pass ## 經過類對象去引用 print(Person.get_country()) print(Person.change_country()) print(Person.get_country()) print(Person.get_data()) 複製代碼
通常不會經過是實例對象去訪問靜態方法post
因爲靜態方法主要存放邏輯方法,自己與類以及實例沒有交互,也就是不會涉及類中方法和屬性的操做網站
根據資源可以有效的利用spa
import time
class sys_time: def __init__(self,hour,min,second): self.hour = hour self.min =min self.second = second @staticmethod ## 獨立的功能 def show_time(): return time.strftime('%H:%M:%S',time.localtime()) print(sys_time.show_time()) ## 15:15:44 複製代碼
1.類方法的第一個參數是類對象,cls進而去引用類對象的屬性和方法
2.實例方法的第一個參數是實例屬性,若存在相同的實例屬性或者方法,實例屬性優先級最高
3.靜態方法不須要額外的參數,若須要引用屬性。,則能夠經過類對象或者實例對象去引用便可,必須使用裝飾器@staticmethod裝飾
## 私有屬性 以__開頭,聲明爲屬性私有,不能在類的外部被使用或者直接訪問。
class Person(object): def __init__(self): self.__name = '叫我詹躲躲' ## 私有化 self.age = '21' pass def __str__(self): return '{}的年齡是{}'.format(self.__name,self.age) person = Person() ## print(person.__name) ##報錯 print(person) ##能夠訪問 ## 叫我詹躲躲的年齡是21 ## 私有屬性,不能被子類繼承 複製代碼
class A(object):
def __eat(self): print('吃飯') pass pass def run(self): print('跑步') pass pass b = A() b.__eat() ## 報錯 b.run() ## 跑步 複製代碼
屬性函數
class A(object):
def __init__(self): self.__name = 18 def __eat(self): return self.__name pass pass def run(self): print('跑步') pass pass age = property(__eat, run) b = A() print(b.age) ## 報錯 b.run() ## 跑步 複製代碼
class A(object):
def __init__(self): self.__name = 18 def __eat(self): return self.__name pass pass def run(self): print('跑步') pass @property ##添加屬性標識 def age(self): return self.__name pass @age.setter ##修改屬性 def age(self,params): self.age = params pass pass p1 = A() print(p1.age) ## 18 p1.age = 16 print(p1.age) 複製代碼
做用:建立並返回一個實例對象,若是__new__只調用了一次,就會獲得一個對象。繼承自object的新式類,纔有new這一魔術方法。
1.__new__是一個實例化調用的第一個方法
2.__new__至少必須有一個參數 cls,表明要實例化的類,此參數在實例化時由python解釋器提供,其餘的參數是直接傳遞給__init__方法 3.__new__決定是否使用該__init__方法,由於__new__能夠調用其餘的類的構造方法或者返回實例對象做爲類的實例,若是__new__沒有返回實例,則__init__不會被調用 4.在__init__方法中,不能調用本身的__new__方法,return cls__new__(cls),不然會報錯。 複製代碼
class A(object):
def __init__(self): print('__init__執行了') pass pass def __new__(cls,*args,**kwargs): return super().__new__(cls,*args,**kwargs) pass pass a = A() print(a) __init__執行了 <__main__.A object at 0x00000291F97D5160> ## 當__new__返回的時候 __init__纔會顯示 複製代碼
class DataBaseClass(object):
def __new__(cls,*args,**kwargs): ## cls._instance = cls.__new__(cls) ##不能使用本身的new方法 if not hasattr(cls,'_instance'): cls._instance = super().__new__(cls,*args,**kwargs) return cls._instance pass pass db1 = DataBaseClass() db2 = DataBaseClass() db3 = DataBaseClass() print(id(db1)) print(id(db2)) print(id(db3)) ## 三個指向的內存地址都同樣的 ## 1852298514784 ## 1852298514784 ## 1852298514784 複製代碼
try:
## 可能出現錯誤的代碼塊 except: ## 出錯以後執行的代碼塊 else: ## 沒有出錯的代碼塊 finally: ## 無論有沒有出錯,都會執行 複製代碼
try:
## 可能出現錯誤的代碼塊 li = [1,2,3] ## print(li[10]) print(1/0) except IndexError as msg: ## 出錯以後執行的代碼塊 print(msg) except ZeroDivisionError as msg: ## 出錯以後執行的代碼塊 print(msg) else: ## 沒有出錯的代碼塊 print('沒有出錯了') finally: ## 無論有沒有出錯,都會執行 print('出錯了') ## 用一個try能夠捕獲多個不一樣類型的異常 複製代碼
try:
print(b) except Exception as result: print(result) else: print('出錯了') finally: print('出錯了') 複製代碼
def A(s):
return s/int(s) pass def B(s): return A(s)/2 pass def main(): try: B(0) except Exception as result: print(result) main() 複製代碼
在合適的位置進行錯誤捕獲
division by zero
1、解釋器會查找相應的異常捕獲類型
2、不斷傳遞給上層,沒有找到異常處理,會退出 複製代碼
class ToolongException(Exception):
def __init__(self, len): self.len = len def __str__(self): return '輸入的長度是'+str(self.len)+'長度,超出長度了' def name_test(): name = input('輸入名字') try: if len(name)>5: raise ToolongException(len(name)) else: print(name) except ToolongException as result: print(result) else: print('沒有出錯了') name_test() ##輸入的長度是13長度,超出長度了 複製代碼
import types class Student: def __init__(self, name, age): self.name = name self.age = age pass pass def __str__(self): return '{}今天{}歲了'.format(self.name, self.age) pass pass zhz = Student('詹躲躲', 25) zhz.wight = 60 def dymicMethod(self): print('{}體重是{}'.format(self.name,self.wight)) pass ## 動態添加屬性 print(zhz.wight) ## 類添加屬性 Student.pro = '計算機科學' ## 實例能夠訪問 print(zhz.pro) ## 動態添加實例方法 ## import types zhz.printInfo = types.MethodType(dymicMethod,zhz) zhz.printInfo() ## 詹躲躲體重是60 複製代碼
import types
class Student: def __init__(self, name, age): self.name = name self.age = age pass pass def __str__(self): return '{}今天{}歲了'.format(self.name, self.age) pass pass zhz = Student('詹躲躲', 25) zhz.wight = 60 def dymicMethod(self): print('{}體重是{}'.format(self.name,self.wight)) pass ## 動態綁定類方法 @classmethod def classTest(cls): print('類方法') pass ## 動態綁定靜態方法 @staticmethod def staticTest(): print('靜態方法') pass 複製代碼
print(zhz.wight)
複製代碼
Student.pro = '計算機科學'
## 實例能夠訪問 print(zhz.pro) 複製代碼
## import types
zhz.printInfo = types.MethodType(dymicMethod,zhz) zhz.printInfo() 複製代碼
Student.testMethod = classTest Student.testMethod() 複製代碼
zhz.testMethod()
複製代碼
Student.statictest = staticTest Student.statictest() 複製代碼
zhz.statictest()
複製代碼
class Student(object):
__slots__ = ('name', 'age', 'score') def __str__(self): return "{},{}".format(self.name, self.age) xw = Student() xw.name = '叫我詹躲躲' xw.age = 25 ## print(xw.__dict__) ## {'name': '叫我詹躲躲', 'age': 25} xw.s11 = '1212' #### 報錯 print(xw) 複製代碼
子類未聲明 slots,不會繼承父類的__slots__,此時子類能夠隨意的屬性賦值
子類聲明瞭,範圍爲 子類+父類的範圍
用來建立實例對象,只有繼承了object的話,纔有這個方法。
要求一個類有且只有一個實例,而且提供了全局的訪問點。日誌插入logger,網站計數器,權限驗證模塊,window資源管理器,系統回收站,數據庫鏈接池
不能的
程序在執行中出現的異常。
分別根據異常的類型去處理
## try:
## 正常操做 ## except: ## ##.... ## else: ## ##.... ## finally: ## ##... 複製代碼
限制屬性的隨意輸入,節省內存空間
保護數據,封裝性的體現
不能夠直接修改,經過方法去實現,能夠藉助property
對屬性進行私有化
提供獲取用戶信息的函數,提供設置私有屬性的方法,設置年齡在0-120歲中間,若是不在這個範圍,不能設置成功
class Person:
def __init__(self,name,age): self.__name = name self.__age = age pass pass def GetUserInfo(self): return "{}的年齡爲{}".format(self.__name,self.__age) pass pass def __str__(self): return "{}的年齡爲{}".format(self.__name,self.__age) def setAge(self,age): if age>0 and age<120: self.__age = age else: pass person = Person('詹躲躲',19) print(person.GetUserInfo()) ## 詹躲躲的年齡爲19 print(person.setAge(30)) print(person.GetUserInfo()) ## 詹躲躲的年齡爲30 複製代碼
class DataBaseClass(object):
def __new__(cls,*args,**kwargs): ## cls._instance = cls.__new__(cls) ##不能使用本身的new方法 if not hasattr(cls,'_instance'): cls._instance = super().__new__(cls,*args,**kwargs) return cls._instance pass pass db1 = DataBaseClass() db2 = DataBaseClass() db3 = DataBaseClass() print(id(db1)) print(id(db2)) print(id(db3)) 複製代碼
class Student:
def __init__(self, name, score): self.__name = name self.___score = score @property def name(self): return self.__name @name.setter def name(self, name): self.__name = name def __str__(self): return self def __call__(self, *args, **kwargs): print(self.name) pass pass xm = Student('詹躲躲',98) xm.__call__() xm.name() 複製代碼
import types
class Animal: pass def run(self): print('小貓') cat = Animal() cat.run = types.MethodType(run,cat) cat.run() Animal.color = 'red' print(cat.color) def info(): print('ok') Animal.info = info Animal.info() 複製代碼