1. 程式人生 > >python-前方高能-面向對象-進階3

python-前方高能-面向對象-進階3

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