python-前方高能-面向對象-進階3
阿新 • • 發佈:2018-08-03
pass 程序 setter 構造方法 類的私有變量 The 父類 是你 wim
面向對象
你寫代碼的時候 什麽時候用面向對象
代碼量大,功能多的時候
處理比較復雜的角色之間的關系
qq 好友 陌生人 群 組
復雜的電商程序
公司/學校的人事管理/功能的系統
我的代碼的清晰度更高了
可讀性 無論是開發者 還是調用者 都能明確的分辨出每個角色擁有的方法和屬性
增強了代碼可擴展性
增加復用性
更加規範
python當中一切皆對象 基礎數據類型 都是對象
類型和自定義類的關系 類型和類是一個東西
type(obj) obj是一個對象,那麽它的type就是它的類型
創建一個對象
類名() 實例化
__new__()創造了一個對象的空間,一些簡單的初始化
創建一個類
class 類名 語法級別的 python解釋器讀到這句話的時候
type是所有類的元類,object是所有類的父類
類也是被創建出來的,type創建類, type(cls) = type
class A(metaclass=ABCMeta) ABCMeta創建了這個A類,那麽ABCMeta就是A的元類
那麽 type就是這個類的 元類
type(obj) 的結果就是這個對象所屬的類
type(類)的結過就是創建這個類的元類,大多數情況下就是type,除非你指定metaclass
類 class Leiming
類是什麽時候被加載的,以及類名是什麽時候生效的
類
靜態屬性/靜態字段/靜態變量
動態屬性/方法
class Person: ROLE = ‘CHINA‘ # print(Person.ROLE) # 報錯 print(ROLE) def func(self): pass a = Person() print(Person.func) print(a.func)
對象
類創造對象的過程就是實例化的過程 : 構造new,初始化init
可以通過指針找到類的空間中的內容
對象本身內部存儲了一些只屬於對象的屬性
組合 什麽有什麽的關系
一個類的對象作為另一個類對象的屬性
繼承 什麽是什麽的關系,節省代碼
子類 和 父類
單繼承 和 多繼承
單繼承
如果子類的對象調用某個方法
子類有 : 調用子類的
子類有但想調父類的 :
super : 不用自己傳self super(子類,self).方法名(除了self之外的參數)
父類名: 父類名.方法名(self,...)
子類沒有 : 找父類
註意 在任何類中調用的方法,都要自習分辨一下這個self到低是誰的對象
class Foo: def __init__(self): self.func() def func(self):print(‘Foo.func‘) class Son(Foo): def func(self):print(‘Son.func‘) s = Son()
多繼承
新式類 : 廣度優先 - C3算法
mro方法查看繼承順序
py3 默認繼承object 所以py3都是新式類
super().func() 遵循mro算法,在類的內部不用傳子類名和self
py2 需要主動繼承object
super(子類名,self).func() 必須傳子類名和self
經典類 : 深度優先
py2 不繼承object,默認都是經典類
沒有mro
class A: def func(self): print(‘A‘) class B(A): def func(self): super().func() print(‘B‘) class C(A): def func(self): super().func() print(‘C‘) class D(B,C): def func(self): super().func() print(‘D‘) d = D() d.func() b= B() b.func()
抽象類和接口類
不能被實例化
規範子類當中必須實現某個方法
有原生的實現抽象類的方法,但是沒有原生實現接口類的方法
抽象類 : 抽象類中的方法是可以實現的 只能單繼承
接口類 : 可以多繼承 但是這個類中的所有方法都不應該實現
java
java 只支持類的單繼承 抽象類 父類的方法可以實現
接口 interface 支持多繼承的規範 接口中的所有方法 只能寫pass
Interface 會飛的動物
fly
會走的動物
walk
會遊泳的動物
swim
老虎(會走的動物,會遊泳的動物)
walk
swim
青蛙(會走的動物,會遊泳的動物)
walk
遊泳
天鵝(會走的動物,會遊泳的動物,會飛的動物)
walk
遊泳
飛
多態 在python當中處處存在
一種類型的多種形態 多個子類去繼承父類,那麽每一個子類都是這個父類的一種形態
class Animal:pass class Tiger(Animal):pass class Frog(Animal):pass
java
def func(Animal laohu_or_frog):
laohu_or_frog.eat()
python
def func(obj): obj.eat()
鴨子類型 規範全憑自覺
封裝 私有的
廣義的封裝 : 把方法和屬性都封裝在一個類裏,定義一個規範來描述一類事物.
狹義的封裝 : 私有化 只能在類的內部訪問
__靜態變量,私有方法,私有的對象屬性,私有的類方法,私有的靜態方法
在內存中存儲 _類名__名字
為什麽在類的內部可以使用雙下劃線訪問 : 在類的內部使用,你就知道你在哪個類中
在子類中可以訪問訪問父類的私有變量麽?不行
私有 : 不能在類的外部使用也不能被繼承
property 裝飾器函數,內置函數,幫助你將類中的方法偽裝成屬性,特性
調用方法的時候不需要主動加括號
讓程序的邏輯性更合理
@方法名.setter 裝飾器,修改被property裝飾的屬性的時候會調用被這個裝飾器裝飾的方法,除了self之外還有一個參數,被修改的值
@方法名.deleter 裝飾器,當要刪除被property裝飾的屬性的時候會調用被這個裝飾器裝飾的方法
# 只用property class Circle: def __init__(self,r): self.r = r # self.area = 3.14*self.r**2 @property def area(self): # 這個方法計算結果本身就是是一個屬性,但是這個屬性會隨著這個類/對象的一些基礎變量的變化而變化 return 3.14*self.r**2 c = Circle(5) print(c.area) c.r = 10 print(c.area)
# 偏其他語言 property+私有的 合用 ,這個時候更多的也會用到setter和deleter class A: def __init__(self,name): self.__name = name @property def name(self): return self.__name @name.setter def name(self,new_name): if type(new_name) is str: self.__name = new_name @name.deleter def name(self): del self.__name a = A(‘alex‘) a.name = 123 print(a.name) del a.name # 語法 print(a.name)
classmethod 類方法的裝飾器 內置函數
使用類名調用,默認傳類名作為第一個參數
不用對象命名空間中的內容,而用到了類命名空間中的變量(靜態屬性),或者類方法或靜態方法
staticmethod 靜態方法的裝飾器 內置函數
如果一個類裏面的方法 既不需要用到self中的資源,也不用cls中的資源.
相當於一個普通的函數
但是你由於某種原因,還要把這個方法放在類中,這個時候,就將這個方法變成一個靜態方法
某種原因:
你完全想用面向對象編程 ,所有的函數都必須寫到類裏
某個功能確確實實是這個類的方法,但是確確實實沒有用到和這個類有關系的資源
反射 - 從某個指定的命名空間中,用字符串數據類型的變量名來獲取變量的值
類名反射 靜態屬性 類方法 靜態方法
對象反射 對象屬性 方法
模塊 模塊中的方法
自己模塊中
import sys
mymodule = sys.modules[‘__main__‘]
getattr(mymodule,‘變量名‘)
hasattr/getattr/setattr/delattr
參數
(命名空間,‘變量名‘)
setattr(命名空間,‘變量名‘,新的值)
變量名 你只能拿到一個字符串的版本
從文件裏拿
交互拿 :input / 網絡傳輸
a = ‘你好‘
print(a.encode(‘utf-8‘))
進階
內置方法/魔術方法/雙下方法
__名字__不是被直接調用的
間接調用 : 內置函數/面向對象中特殊語法/python提供的語法糖
__str__ : str(obj),要求必須實現了__str__,要求這個方法的返回值必須是字符串str類型
print %s str
__call__ : 對象() 用類寫裝飾器
__len__ : len(obj),要求obj必須實現了__len__,要求這個方法的返回值必須是數字int類型
__new__ : 在實例化的過程中,最先執行的方法,在執行init之前,用來創造一個對象,構造方法
單例類
__init__ : 在實例化的過程中,在new執行之後,自動觸發的一個初始化方法
__str__ : str(obj),要求必須實現了__str__,要求這個方法的返回值必須是字符串str類型
print %s str
__repr__: 是__str__的備胎.如果有__str__方法,那麽# print %s str都先去執行__str__方法,並且使用__str__的返回值
如果沒有__str__,那麽 print %s str都會執行repr
repr(obj),%r
在子類中使用__str__,先找子類的__str__,沒有的話要向上找,只要父類不是object,就執行父類的__str__
但是如果出了object之外的父類都沒有__str__方法,就執行子類的__repr__方法,如果子類也沒有,
還要向上繼續找父類中的__repr__方法.
一直找不到 再執行object類中的__str__方法
a = ‘123‘ print(a) print(repr(a)) class A: def __init__(self,name): self.name = name def __str__(self): return ‘**%s**‘%self.name def __repr__(self): return self.name class B(A): def __init__(self,name): self.name = name def __repr__(self): return ‘***‘ a = B(‘alex‘) print(a) print(str(a),repr(a)) print(‘%s | %r‘%(a,a)) print(‘---%r---‘%(‘abc‘)) print(‘---%s---‘%(‘abc‘))
x = 5 y = 6 print(x.__add__(y)) print(x+y) # 語法糖 class MyType: def __init__(self,s): self.s = s def __add__(self, other): # __sub__ __mul__ __div__ return self.s.count(‘*‘) + other.s.count(‘*‘) obj1 = MyType(‘asjkfhk***17264****‘) obj2 = MyType(‘asjkfhk***17***‘) print(obj1 + obj2) print(obj1.__add__(obj2)) print(‘ashglhg**uowqeyo88‘.count(‘*‘))
面向對象總結:
https://www.processon.com/mindmap/5b5fb02de4b0f8477d9b2b89
python-前方高能-面向對象-進階3