1. 程式人生 > 其它 >23.多型 面向物件內建函式 即相關知識

23.多型 面向物件內建函式 即相關知識

1.多型
    概念: 一種事物具備多種不同形態
    例如: 水  固態 氣態 液態
        大黃蜂:汽車人,汽車,飛機
    官方解釋: 多個不同類物件可以響應同一個方法,產生不同的結果

    首先強調多型不是一種特殊的語法,而是一種狀態,特性(既多個不同物件可以響應同一個方法,產生不同的結果 )
     既多個物件有相同的使用方法,

     好處:
        對於使用者而言,大大的降低了使用難度
        我們之前寫的USB介面,下的滑鼠,鍵盤,就屬於多型

1.實現多型: # 1.多型性的實現.py
  介面 抽象類 鴨子型別 都可以寫出具備多型的程式碼,最簡單的就是鴨子型別

2.oop相關內建函式.py ## isinstance 判斷一個物件是否是某個類的例項 引數1 要判斷的物件 引數2 要判斷的型別 ## issubclass 判斷一個類是否是另一個類的子類 引數一是子類 引數二是父類 3.類中的魔法函式 __str__: 會在物件被轉換為字串時,轉換的結果就是這個函式的返回值 使用場景 :我們可以用函式來自定義, 物件的列印格式 del : 執行時機: 手動刪除物件時立馬執行,或是程式執行結束時也會自動執行 使用場景: 當你的物件在使用的過程中,打開了不屬於直譯器的資源:例如 檔案,網路埠 call : 執行時機:在呼叫物件時自行執行,即物件
+() slots :該屬性是一個類屬性,用於優化物件 記憶體佔用,優化的原理,將不固定的屬性數量變得固定,這樣的直譯器就不會為這個物件建立名稱空間,所以__dict__ 也沒了 從而達到節省開銷的效果 4.屬性的 get set 和 del.py getattr : 用於訪問屬性時如果屬性不存在時執行 setattr 用於設定屬性點時 delattr 用del 物件.屬性 刪除屬性時執行 這幾個函式反映了 Python直譯器是 如何實現 用點來訪問屬性 getattribute 該函式也是用來獲取屬性,在獲取屬性時如果存在 getattribute則先執行該函式,如果沒有拿到屬性則繼續呼叫 getattr函式 ,如果拿到了則直接返回
5.[] 的 實現原理 getitem setitem delitem 任何的符號,都會被直譯器解釋成特殊含義,例如. [] () getitem 當你用中括號去獲取屬性時執行 setitem 當你用中括號去設定屬性時執行 delitem 當你用中括號刪除屬性時執行 6.運算子過載 當我們在 使用 某個符號時,Python 直譯器 都會為這個符號定義 一個含義,同時呼叫對應的處理函式,當我們需要自定義 物件的 比較規則 時,就可以在子類中 覆蓋 大於 等於 等一系類方法... 案例: 原本自定義物件無法直接使用大於小於來進行比較 ,我們可自定義運算子來實現,讓自定義物件也支援比較運算子 """ 上述程式碼中,other指的是另一個參與比較的物件, 大於和小於只要實現一個即可,符號如果不同 直譯器會自動交換兩個物件的位置 """ 7.迭代器協議: 迭代器是指具有__iter__和__next__的物件 我們可以為物件增加這兩個方法來讓物件變成一個迭代器 8.上下文管理 上下文 context 這個概念屬於語言學科,指的是一段話的意義,要參考當前的場景,既上下文 在 Python中 ,上下文 可以 理解為 是程式碼區間 ,一個範圍 例如with open 開啟的檔案僅在這個上下文中有效 涉及到的兩個方法: enter 表示 進入上下文 (進入某個場景) exit 表示 退出上下文 (退出某個場景) 當執行with 語句時,會先執行enter , 當代碼執行完畢後執行exit,或者程式碼遇到了異常會立即執行exit,並傳入錯誤資訊 包含錯誤的型別.錯誤的資訊.錯誤的追蹤資訊 ps: enter 函式應該返回物件自己 exit函式 可以有返回值,是一個bool型別,用於表示異常是否被處理,僅在上下文中出現異常有用 如果為True 則意味著,異常以及被處理了 False,異常未被處理,程式將中斷報錯 多型 是一種狀態,如果程式具備這種狀態,物件的使用者,可以很方便忽略物件之間的差異 我們可以通過鴨子型別來讓程式具備多型性 一對函式 isinstance 優先 issubclass 優先 類中的魔法函式 str 優先 del 優先 call slots 點語法的 實現 getattr setattr delattr []取值的實現 getitem setitem delitem 運算子過載,可以讓物件具備相互間比較的能力 迭代器的兩個函式 iter next 上下文管理 優先 可以實現自動清理 與del的區別 del管理的是物件的生命週期 會在物件銷燬時執行清理 上下文管理,管理的是一個程式碼範圍 ,出了範圍自動清理
23.多型 面向物件內建函式 即相關知識
"""
要管理 雞 鴨 鵝
如何能夠最方便的 管理,就是我說同一句話,他們都能理解
他們擁有相同的方法

"""
class JI:
    def bark(self):
        print("哥哥哥")

    def spawn(self):
        print("下雞蛋..")

class Duck:
    def bark(self):
        print("嘎嘎嘎")

    def spawn(self):
        print("下鴨蛋")

class E:
    def bark(self):
        print("餓餓餓....")

    def spawn(self):
        print("下鵝蛋..")

j = JI()
y = Duck()
e = E()

def mange(obj):
    obj.spawn()
    obj.bark()

mange(j)
mange(y)
mange(e)


"""
python 中到處都有多型
"""
a = 10
b = "10"
c = [10]

print(type(a))
print(type(b))
print(type(c))
1.多型性的實現.py
def add_num(a,b):
    if isinstance(a,int) and isinstance(b,int):
        return a+b
    return None

print(add_num(20,10))

class Animal:
    def eat(self):
        print("動物的吃東西...")

class Pig(Animal):
    def eat(self):
        print("豬得吃 豬食....")

class Tree:
    def light(self):
        print("植物光合作用....")

pig = Pig()
t = Tree()

def manage(obj):
    if issubclass(type(obj),Animal):
        obj.eat()
    else:
        print("不是動物")


# manage(pig)

manage(t) # 不是動物
print(issubclass(Tree,object)) # True
2.oop相關內建函式.py
import sys
import time
"""
__str__ 物件 轉換 字串 就是 這個函式的返回值 自定義物件的列印格式  
"""
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def __str__(self):
        return "這個一個person物件 name:%s age:%s" % (self.name,self.age)

    def __del__(self):
        print("del run")


p = Person("jack",20)
# del p
time.sleep(2)
print(str(p)) # 這個一個person物件 name:jack age:20
print("over")


"""del 使用案例"""
"""
呼叫del 或者 程式執行結束
"""
class FileTool:
    """
    該類用於簡化檔案的讀寫操作
    """
    def __init__(self,path):
        self.file = open(path,'rt',encoding="utf-8")
        self.a = 100

    def read(self):
        return self.file.read()

    # 在這裡可以確定一個事,這個物件肯定不使用了 所以可以放心的關閉問檔案了
    def __del__(self):
        self.file.close()

tool = FileTool("a.txt")
print(tool.read())

"""call 呼叫物件 (物件+() 執行)"""

class A:
    def __call__(self,*args,**kwargs):
        print("call run")
        print(args)
        print(kwargs)

a = A()
a(1,a = 100)

"""slots 優化記憶體"""
class Person:
    __slots__ = ["name"]
    def __init__(self,name):
        self.name = name
        # print(self.__dict__)

p = Person("jac")
print(sys.getsizeof(p))
# p.age = 20
# dict 沒有了
print(p.__dict__)
3.類中的魔法函式.py
class A:
    def __setattr__(self, key, value):
        print(key)
        print(value)
        print("__setattr__")
        self.__dict__[key] = value

    def __delattr__(self,item):
        print("__delattr__")
        print(item)
        self.__dict__.pop(item)
        pass
    def __getattr__(self, item):
        print("__getattr__")
        return 1

    def __getattribute__(self, item):
        print("__getattribute__")
        # return self.__dict__[item]
        return super().__getattribute__(item)

a = A()
a.name = "jack"
print(a.name) # jack
# del a.name
# print(a.xxx)
# a.name = "xxx"
# print(a.name)


b = A()
b.__dict__["name"] = "jack"
print(b.name)
4.屬性的 get set 和 del.py
class A:
    def __getitem__(self,item):
        print("__getitem__")
        return self.__dict__[item]
    def __setitem__(self, key, value):
        print("__setitem__")
        self.__dict__[key] = value
    def __delitem__(self,key):
        del self.__dict__[key]
        print("__delitem__")

a = A()
# # a.name = "jack"
a["name"] = "jack"
print(a['name'])

# del a["name"]
# print(a["name"])
5.getitem setitem delitem.py
""""""
"""
案例:

原本自定義物件無法直接使用大於小於來進行比較 ,我們可自定義運算子來實現,讓自定義物件也支援比較運算子  

"""
class Student(object):
    def __init__(self,name,height,age):
        self.name = name
        self.height = height
        self.age = age

    def __gt__(self,other):
        print(self)
        print(other)
        print("__gt__")
        return self.height > other.height

    def __lt__(self,other):
        return self.height < other.height

    def __eq__(self, other):
        if self.name == other.name and self.age == other.age and self.height == other.height:
            return True
        return False

stu1 = Student("jack",180,28)
stu2 = Student("jack",180,28)

print(stu1 < stu2) # False
print(stu1 == stu2)

"""
上述程式碼中,other指的是另一個參與比較的物件,

大於和小於只要實現一個即可,符號如果不同  直譯器會自動交換兩個物件的位置 
"""
6.物件比較大小.py
# class MyIter:
#     """
#     num 傳入 用來指定迭代次數
#     """
#     def __init__(self,num):
#         self.num = num
#         self.c = 0
#
#     def __iter__(self):
#         return self
#
#     def __next__(self):
#         self.c += 1
#         if self.c <= self.num:
#             return "哈哈"
#         else:
            # raise StopIteration
#
# for i in MyIter(10):
#     print(i)
# for i in range(1,10):
#     print(i)

# for i in [1,2,3,4]:
#     pass


# 實現一個自定義的range

class MyRange:
    def __init__(self,start,end,step):
        self.start = start
        self.end = end
        self.step = step

    def __iter__(self):
        return self

    def __next__(self):
        a = self.start
        self.start += self.step
        if a < self.end:
            return a
        else:
            raise StopIteration

for i in MyRange(1,10,2):
    print(i)

"""
1
3
5
7
9
"""
7.迭代器.py
class MyOpen(object):

    def __init__(self,path):
        self.path = path

    def __enter__(self):
        self.file = open(self.path)
        print("enter...")
        return self

    def __exit__(self,exc_type,exc_val,exc_tb):
        print("exit...")
        print(exc_type,exc_val,exc_tb)
        self.file.close()
        return True

with MyOpen("a.txt") as m:
    print(m)
    print(m.file.read())
    "123"+1

"""
enter...
<__main__.MyOpen object at 0x000001B9A82C45F8>
asasasa
exit...
<class 'TypeError'> must be str, not int <traceback object at 0x000001B9B7382D48>

"""
# m.file.read()
8.上下文管理.py

 

動態容器實現原理.png