python面型對象編程進階(繼承、多態、私有化、異常捕獲、類屬性和類方法)

原創:叫我詹躲躲
來源:掘金
連接:python面型對象編程進階(繼承、多態、私有化、異常捕獲、類屬性和類方法)
致謝:感謝求知教育提供的視頻教程python

1.單繼承

## 封裝,繼承和多態
## 1.封裝 1、知足把內容封裝到某個地方,另外一個地方去調用封裝的內容 2、使用初始化構造方法,或者使用self獲取封裝的內容  ## 2.繼承 子類繼承父類的屬性和內容 複製代碼

1.1單繼承示例

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()  ## 總結:因此對於面向對象的繼承來講,能夠極大的提高效率,減小重複代碼 複製代碼

2.多繼承

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()  複製代碼

2.1 注意方法重名:

## 多個父類存在相同的方法,該調用哪個
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類中查找; 複製代碼

2.2案例 簡潔繼承

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'>  複製代碼

2.3重寫父類方法

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__)  ## 定義跟父類相同的方法,能夠實現覆蓋和重寫父類的方法 複製代碼

2.4重寫初始化方法

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__) 複製代碼

2.5調用父類初始化方法

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')  複製代碼

2.6 調用父類的方法

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()  ## 父類的吃方法 ## 子類的吃方法 複製代碼

3 多態

同一種行爲,對於不一樣子類【對象】有不一樣的實現方式web

3.1 要想實現多態,必須有兩個前提

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)  ## 在定義時的類型跟調用時不同的時候,稱爲多態。 複製代碼

3.2 多態的好處

1.增長程序的靈活性ide

2.增長程序的擴展性函數

4.類屬性和實例屬性

## 類屬性:就是類對象擁有的屬性,它被全部類對象的實例對象所共有,類對象和實例對象能夠訪問。
## 實例屬性:實例對象所擁有的屬性,只能經過實例對象訪問。  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)  ## 總結 ## 類屬性:類對象和實例對象均可以訪問 ## 實例屬性:只能由實例屬性訪問  ## 全部的實例對象指向同一類對象 ## 實例對象去修改類屬性 不能修改 ## 類對象能夠修改類屬性 能夠修改  複製代碼

5.類屬性和靜態方法

## 裝飾器@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()) 複製代碼

5.1 靜態方法

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

5.2求系統當前的時間

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  複製代碼

5.3 總結

1.類方法的第一個參數是類對象,cls進而去引用類對象的屬性和方法

2.實例方法的第一個參數是實例屬性,若存在相同的實例屬性或者方法,實例屬性優先級最高

3.靜態方法不須要額外的參數,若須要引用屬性。,則能夠經過類對象或者實例對象去引用便可,必須使用裝飾器@staticmethod裝飾

6.私有化

6.1 私有化屬性

## 私有屬性 以__開頭,聲明爲屬性私有,不能在類的外部被使用或者直接訪問。
 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  ## 私有屬性,不能被子類繼承 複製代碼

6.2私有化方法

class A(object):
 def __eat(self):  print('吃飯')  pass  pass   def run(self):  print('跑步')  pass  pass  b = A() b.__eat() ## 報錯 b.run() ## 跑步 複製代碼

7.property方法

屬性函數

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() ## 跑步 複製代碼

7.1 @age.setter ##修改屬性

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) 複製代碼

8. __new__方法

做用:建立並返回一個實例對象,若是__new__只調用了一次,就會獲得一個對象。繼承自object的新式類,纔有new這一魔術方法。

8.1 注意事項

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__纔會顯示 複製代碼

9.單例模式

9.1 確保一個類只有一個實例存在,使用__new__

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  複製代碼

10 錯誤和異常處理

try:
 ## 可能出現錯誤的代碼塊 except:  ## 出錯以後執行的代碼塊 else:  ## 沒有出錯的代碼塊 finally:  ## 無論有沒有出錯,都會執行 複製代碼

10.1 錯誤和異常處理示例

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能夠捕獲多個不一樣類型的異常 複製代碼

10.2 使用 Exception處理全部錯誤

try:
 print(b) except Exception as result:  print(result) else:  print('出錯了') finally:  print('出錯了')  複製代碼

10.3在合適的層次去捕獲

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

10.4 異常運行機制

1、解釋器會查找相應的異常捕獲類型
2、不斷傳遞給上層,沒有找到異常處理,會退出 複製代碼

11.自定義異常類型

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長度,超出長度了   複製代碼

12 動態添加屬性和方法

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  複製代碼

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  ## 動態綁定類方法 @classmethod def classTest(cls):  print('類方法')  pass  ## 動態綁定靜態方法 @staticmethod def staticTest():  print('靜態方法')  pass 複製代碼

13.1.動態添加屬性

print(zhz.wight)
複製代碼

13.2.類添加屬性

Student.pro = '計算機科學'
## 實例能夠訪問 print(zhz.pro) 複製代碼

13.3.動態添加實例方法

## import types
zhz.printInfo = types.MethodType(dymicMethod,zhz) zhz.printInfo() 複製代碼

13.4.動態綁定類方法

Student.testMethod = classTest
Student.testMethod() 複製代碼

13.5.動態綁定類方法 實例調用

zhz.testMethod()
複製代碼

13.6.動態綁定靜態方法

Student.statictest = staticTest
Student.statictest() 複製代碼

13.7.動態綁定靜態方法 實例調用

zhz.statictest()
複製代碼

14._slots_屬性

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__,此時子類能夠隨意的屬性賦值

子類聲明瞭,範圍爲 子類+父類的範圍

15.題目練習 一

15.1 python new的方法和做用是什麼?

用來建立實例對象,只有繼承了object的話,纔有這個方法。

15.2 什麼是單例模式,適用於什麼場景?

要求一個類有且只有一個實例,而且提供了全局的訪問點。日誌插入logger,網站計數器,權限驗證模塊,window資源管理器,系統回收站,數據庫鏈接池

15.3 私有化方法和私有化屬性在子類中可否繼承?

不能的

15.4 在python中什麼是異常?

程序在執行中出現的異常。

15.5 python中如何處理異常?

分別根據異常的類型去處理

15.6 python中異常處理的通常格式,可使用僞代碼描述?

## try:
## 正常操做 ## except: ## ##.... ## else: ## ##.... ## finally:  ## ##... 複製代碼

15.7 __slots__的做用

限制屬性的隨意輸入,節省內存空間

15.8 私有化的屬性的做用?

保護數據,封裝性的體現

15.9 在類外是否修改私有屬性?

不能夠直接修改,經過方法去實現,能夠藉助property

15.10 若是一個類,只有指定的屬性或者方法能被外部修改,該如何限制?

對屬性進行私有化

16 題目練習二

16.1 定義一個person類,類中要有初始化方法,方法中要有人名,年齡兩個私有屬性

提供獲取用戶信息的函數,提供設置私有屬性的方法,設置年齡在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  複製代碼

16.2 請寫一個單例模式

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))  複製代碼

16.3 建立一個類,並定義兩個私有化屬性,提供一個獲取屬性的方法。利用property屬性給調用者提供調用

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() 複製代碼

16.4 建立一個Animal類。實例一個cat對象,給cat 綁定一個run方法,給類綁定一個類屬性color

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() 複製代碼
相關文章
相關標籤/搜索