面向對象的由來html
ps : 一個軟件質量因素有不少: 性能, 可維護, 可擴展, 可移植, 成本, 安全......, 而面向對象解決的僅僅是可擴展性的問題, 因此它也是有侷限性的python
⛅在沒有學習類這個概念時,數據與功能是分離的 ⛅每次調用都須要重複傳入一堆參數, 咱們能想到的解決方法是,把這些變量都定義成全局變量 ⛅這樣咱們將會定義一大堆全局變量,這些全局變量並無作任何區分,即可以被全部功能使用 ⛅然而事實上只有某一些對象才使用某一些它們所須要的功能, 並非所有的功能都須要 ⛅言外之意:咱們必須找出一種可以將數據與操做數據的方法組合到一塊兒的解決方法,這就是咱們說的類了
⛅"現實世界中 : 先有對象, 再有類 世界上現實有了各類各樣的物種:豬,狗,貓,人,而後咱們將其歸爲:豬類,犬類,貓類,人類 ⛅"在程序中 : 先有類, 再有對象 與函數相似, 先定義再調用, 類也是同樣, 先定義類, 再調用類 不一樣的是函數調用時執行函數體代碼, 而類則是實例出一個對
🐫製造一個"鴨子對象",鴨子有不一樣品種"特徵", 鴨子會叫, 還會跑這些"技能" (特徵與對象的結合體: 就是屬性與方法) ⛅先定義一個"鴨子類" class Duck: ⛅特徵(屬性) bread = "你好鴨" color = "yello" ⛅技能(方法),特殊的函數,自帶"self" def run(self): print("技能奔跑") ⛅定義一個"鴨子對象" duck1 = Duck() ⛅使用對象 print(duck1.bread) # 你好鴨 print(duck1.color) # yello duck1.run() # 技能奔跑
__dict__
: 類的名稱空間[類名].__dict__
來進行查看.__dict__
來查看🐫"."(點)專門用來訪問屬性, 本質上就是在操做"__dict__" print(Duck.__dict__) '''輸出結果 {'__module__': '__main__', 'bread': '你好鴨', 'color': 'yello',\ 'run': <function Duck.run at 0x000001FB5771FC18>, '__dict__': <attribute '__dict__' of 'Duck' objects>,\ '__weakref__': <attribute '__weakref__' of 'Duck' objects>, '__doc__': None} '''「__」開頭的能夠先不要關注 Duck.bread # 等於經典類的操做 : Duck.__dict__["bread"] Duck.color = "black" # 等於經典類的操做 : Duck.__dict__["color"] = "black" Duck.new_x = "haha" # 等於經典類的操做 : Duck.__dict__["new_x"] = "haha" del Duck.new_x # 等於經典類的操做 : Duck.__dict__.pop("new_x")
class Duck: bread = "你好鴨" color = "yello" "self" def run(self): print("技能奔跑") duck1 = Duck() duck1.name = "哎鴨" # 定製獨有的品種 duck1.color = "black" # 定製獨有的顏色 duck1.weight = 20 # 定製獨有的重量 print(duck1.name) # 哎鴨 print(duck1.color) # black print(duck1.weight) # 20
__init__
方法🐫上面咱們介紹了一種給對象定製獨有特徵的方法,下面咱們使用"__init__"方法直接進行初始化賦值 ⛅新方案, 只要是類實例化獲得對象, 就會自動觸發"__init__"的執行 class Duck: def __init__(self): self.bread = "你好鴨" self.color = "yello" def run(self): print(f"{self.bread}有技能奔跑") duck1 = Duck() print(duck1.bread) # 你好鴨 print(duck1.color) # yello duck1.run() # 你好鴨有技能奔跑 ⛅"__init__"的升級使用, 觸發"__init__"的執行, 並傳入參數(傳參原則與函數傳參相同) class Duck: def __init__(self,bread,color): self.bread = bread self.color = color def run(self): print(f"{self.bread}有技能奔跑") duck1 = Duck("快跑鴨","black") duck2 = Duck("能夠鴨","blue") duck3 = Duck("牛鴨","white") print(duck1.bread) # 快跑鴨 print(duck1.color) # black duck1.run() # 快跑鴨有技能奔跑 print(duck2.bread) # 能夠鴨 print(duck2.color) # blue duck2.run() # 能夠鴨有技能奔跑 print(duck3.bread) # 牛鴨 print(duck3.color) # white duck3.run() # 牛鴨有技能奔跑
ps : id是python的實現機制,並不能真實反映內存地址,若是有內存地址,仍是之內存地址爲準編程
class Duck: master = "shawn" def __init__(self,bread,size): self.bread = bread self.size = size duck1 = Duck("嘿鴨",100) duck2 = Duck("好的鴨",80) print(id(duck1.master)) # 1905145581488 print(id(duck2.master)) # 1905145581488
class Duck: master = "shawn" def __init__(self,bread,size): self.bread = bread self.size = size def run(self): print(f"{self.bread}在跑") duck1 = Duck("嘿鴨",100) duck2 = Duck("好的鴨",80) duck3 = Duck("別鴨",80) print(Duck.run) # <function Duck.run at 0x000001F46C919168> print(duck1.run) # <bound method Duck.run of <__main__.Duck object at 0x000001F46C693E08>> print(duck2.run) # <bound method Duck.run of <__main__.Duck object at 0x000001F46C8F3E48>> print(duck3.run) # <bound method Duck.run of <__main__.Duck object at 0x000001F46C8F3E88>>
⛅對象更改屬性, 該的只是本身的 class Duck: master = "shawn" def __init__(self,bread,size): self.bread = bread self.size = size def run(self): print(f"{self.bread}在跑") duck1 = Duck("不要鴨",80) duck1.master = "song" # 更改屬性 print(Duck.master) # shawn print(duck1.master) # song ⛅類修改 class Duck: master = "shawn" def __init__(self,bread,size): self.bread = bread self.size = size def run(self): print(f"{self.bread}在跑") duck1 = Duck("醬紫鴨",80) Duck.master = "xing" # 類修改屬性 print(Duck.master) # xing print(duck1.master) # xing
ps : self能夠是任意名字,可是約定俗成地寫成self安全
__init__
是同樣的道理class Duck: master = "shawn" def __init__(self,bread,size): self.bread = bread self.size = size def run(self): print(f"{self.bread}在跑") def eat(self): print(f"{self.bread}在吃東西") def sleep(self): print(f"{self.bread}在睡覺") duck1 = Duck("可惡鴨",80) duck2 = Duck("厲害鴨",50) duck3 = Duck("好慘鴨",90) duck1.run() # 可惡鴨在跑 duck2.eat() # 厲害鴨在吃東西 duck3.sleep() # 好慘鴨在睡覺
Duck.run(duck1) # 可惡鴨在跑 Duck.eat(duck2) # 厲害鴨在吃東西 Duck.sleep(duck3) # 好慘鴨在睡覺
list1 = list([1,2,3]) dict1 = dict({"name":"shawn"}) int1 = int("12311321") float1 = float("11.3") tuple1 = tuple((1,2,3)) set1 = set(list1) print(type(list1)) # <class 'list'> print(type(dict1)) # <class 'dict'> print(type(int1)) # <class 'int'> print(type(float1)) # <class 'float'> print(type(tuple1)) # <class 'tuple'> print(type(set1)) # <class 'set'>
⛅使用"list"類實例化出一個對象 list1 = list([1,2,3,4]) list2 = list([5,6,6,8]) ⛅每一個對象均可以使用"list"類的公共屬性和方法,咱們稱之爲綁定方法,而且綁定給不一樣的對象, 內存地址也不相同 print(list1.append) # <built-in method append of list object at 0x000001A950EAF108> print(list2.append) # <built-in method append of list object at 0x000001A950EAF188> ⛅實例化出來的每一個對象都是相互獨立的個體, 相互不影響 list1.append(1) list2.insert(0,9) print(list1) # [1, 2, 3, 4, 1] print(list2) # [9, 5, 6, 6, 8]
在上述介紹類與對象的使用過程當中,咱們更多的是站在底層原理的角度去介紹類與對象之間的關聯關係app
若是隻是站在使用的角度,咱們無需考慮語法「對象.屬性"中」屬性「到底源自於哪裏,只須要知道是經過對象獲取到的就能夠了函數
因此說,對象是一個高度整合的產物,有了對象,咱們只須要使用」對象.xxx「的語法就能夠獲得跟這個對象相關的全部數據與功能,十分方便且解耦合程度極高性能