Python基础知识(第八天)
105.方法沒有重載_方法的動態性
方法沒有重載
在其他語言中,可以定義多個重名的方法,只要保證方法簽名唯一即可。方法簽名包含 3 個部分:方法名、參數數量、參數類型。
Python?中,方法的的參數沒有聲明類型(調用時確定參數的類型),參數的數量也可以由可變參數控制。因此,Python?中是沒有方法的重載的。定義一個方法即可有多種調用方式, 相當于實現了其他語言中的方法的重載。
如果我們在類體中定義了多個重名的方法,只有最后一個方法有效。建議:不要使用重名的方法!Python?中方法沒有重載。
方法的動態性
Python 是動態語言,我們可以動態的為類添加新的方法,或者動態的修改類的已有的方法。
class Person:def work(self):print("努力上班!")def play_game(self):print("{0}玩游戲".format(self))def work2(s):print("好好工作,努力上班!")Person.play = play_game Person.work = work2 p = Person() p.play() p.work() <__main__.Person object at 0x7fc89832ff10>玩游戲 好好工作,努力上班!106.私有屬性
Python?對于類的成員沒有嚴格的訪問控制限制,這與其他面向對象語言有區別。關于私有屬性和私有方法,有如下要點:
1.通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public)。
2.類內部可以訪問私有屬性(方法)
3.類外部不能直接訪問私有屬性(方法)
4.類外部可以通過“_類名__私有屬性(方法)名”訪問私有屬性(方法)
class Employee:def __init__(self,name,age):self.name = nameself.__age = agee=Employee("高奇",18) print(e.name) print(e._Employee__age ) 高奇 18107.私有方法
class Employee:def __init__(self,name,age):self.name = nameself.__age = agedef __work(self):print("好好工作!")e= Employee("高淇",32) print(e._Employee__work()) 好好工作!108.@property裝飾器_get和set方法
@property 裝飾器
@property 可以將一個方法的調用方式變成“屬性調用”。
class Employee:def __init__(self,name,salary):self.__name = nameself.__salary = salary@propertydef salary(self):return self.__salary@salary.setterdef salary(self,salary):if 1000<salary<50000: self.__salary=salaryelse:print("輸入錯誤")emp1=Employee("高崎",30000) print(emp1.salary) emp1.salary=2000 print(emp1.salary) 30000 2000109.面向對象的三大特征說明(封裝、繼承、多態)
面向對象三大特征介紹
Python 是面向對象的語言,也支持面向對象編程的三大特性:繼承、封裝(隱藏)、多態。
封裝(隱藏)
隱藏對象的屬性和實現細節,只對外提供必要的方法。相當于將“細節封裝起來”,只 ???對外暴露“相關調用方法”。通過前面學習的“私有屬性、私有方法”的方式,實現“封裝”。Python 追求簡潔的語法,沒有嚴格的語法級別的“訪問控制符”,更多的是依靠程序員自覺實現。
繼承
繼承可以讓子類具有父類的特性,提高了代碼的重用性。從設計上是一種增量進化,原有父類設計不變的情況下,可以增加新的功能,或者改進 ???已有的算法。
多態
多態是指同一個方法調用由于對象不同會產生不同的行為。生活中這樣的例子比比皆 ???是:同樣是休息方法,人不同休息方法不同。張三休息是睡覺,李四休息是玩游戲,程序員休息是“敲幾行代碼”。
110.繼承
繼承是面向對象程序設計的重要特征,也是實現“代碼復用”的重要手段。
如果一個新類繼承自一個設計好的類,就直接具備了已有類的特征,就大大降低了工作難度。已有的類,我們稱為“父類或者基類”,新的類,我們稱為“子類或者派生類”。
Python?支持多重繼承,一個子類可以繼承多個父類。繼承的語法格式如下:
class 子類類名(父類?1[,父類?2,...]):
類體
如果在類定義中沒有指定父類,則默認父類是 object?類。也就是說,object?是所有類的父類,里面定義了一些所有類共有的默認實現,比如:? ? ?new? ??()。
定義子類時,必須在其構造函數中調用父類的構造函數。調用格式如下: ??父類名.? ??init? ??(self, 參數列表)
class Person:def __init__(self,name,age): self.name = nameself.age = agedef say_age(self):print("年齡,年齡,我也不知道")class Student(Person):def __init__(self,name,age,score): Person.__init__(self,name,age) #必須顯示的調用父類初始化方法,不然解釋器不會去調用self.score = scores=Student("高崎",18,60) s.say_age() 年齡,年齡,我也不知道子類不能調用父類私有的屬性
111.方法的重寫
類成員的繼承和重寫
成員繼承:子類繼承了父類除構造方法之外的所有成員。
方法重寫:子類可以重新定義父類中的方法,這樣就會覆蓋父類的方法,也稱為“重寫”
class Person:def __init__(self,name,age): self.name = nameself.age = agedef say_age(self):print(self.name,"的年齡是:",self.age)def say_name(self):print("我是",self.name)class Student(Person):def __init__(self,name,age,score): Person.__init__(self,name,age) #必須顯示的調用父類初始化方法,不然解釋器不會去調用self.score = score def say_score(self):print(self.name,"的分數是:",self.score)def say_name(self):print("報告老師,我的名字是",self.name) s=Student("高崎",18,60) s.say_age() s.say_name() 高崎 的年齡是: 18 報告老師,我的名字是 高崎112.object根類_dir()
查看類的繼承層次結構
通過類的方法 mro()或者類的屬性?mro?可以輸出這個類的繼承層次結構。
class A:pass class B(A):pass class C(B):passprint(C.mro())object 根類
object?類是所有類的父類,因此所有的類都有 object?類的屬性和方法。我們顯然有必要深入研究一下 object?類的結構。對于我們繼續深入學習 Python?很有好處。
dir()查看對象屬性
為了深入學習對象,我們先學習內置函數 dir(),他可以讓我們方便的看到指定對象所有的屬性。
113.重寫__str__()方法
class Person:def __init__(self,name,age): self.name = name self.age = agedef __str__(self):return "名字是:{0},年齡是{1}".format(self.name,self.age)p = Person("高淇",18) print(p)114.多重繼承
Python 支持多重繼承,一個子類可以有多個“直接父類”。這樣,就具備了“多個父類”的特點。但是由于,這樣會被“類的整體層次”搞的異常復雜,盡量避免使用。
115.mro().mp4
Python 支持多繼承,如果父類中有相同名字的方法,在子類沒有指定父類名時,解釋器將“從左向右”按順序搜索。
MRO(Method Resolution Order):方法解析順序。 我們可以通過mro()方法獲得“類的層次結構”,方法解析順序也是按照這個“類的層次結構”尋找的。
116.super()獲得父類的定義
在子類中,如果想要獲得父類的方法時,我們可以通過 super()來做。
class A:def say(self):print("A: ",self)class B(A):def say(self):#A.say(self) super().say()print("say BBB")b = B() b.say()117.多態
多態(polymorphism)是指同一個方法調用由于對象不同可能會產生不同的行為。在現實生活中,我們有很多例子。比如:同樣是調用人的休息方法,張三的休息是睡覺,李四的休息是玩游戲,高淇老師是敲代碼。同樣是吃飯的方法,中國人用筷子吃飯,英國人用刀叉吃飯,印度人用手吃飯。
1.多態是方法的多態,屬性沒有多態。
2.多態的存在有 2?個必要條件:繼承、方法重寫。
class Animal:def shout(self):print("動物叫了一聲")class Dog(Animal):def shout(self):print("小狗,汪汪汪")class Cat(Animal):def shout(self):print("小貓,喵喵喵")def animalShout(a):if isinstance(a,Animal):a.shout() animalShout(Dog()) animalShout(Cat()) 小狗,汪汪汪 小貓,喵喵喵118.特殊方法和運算符重載
Python 的運算符實際上是通過調用對象的特殊方法實現的。
a = 20 b = 30 c = a+b d = a.__add__(b) print("c=",c) print("d=",d)| 方法 | 說明 | 例子 |
| ????init?? | 構造方法 | 對象創建:p = Person() |
| ????del?? | 析構方法 | 對象回收 |
| ????repr__,?str?? | 打印,轉換 | print(a) |
| ????call?? | 函數調用 | a() |
| ????getattr?? | 點號運算 | a.xxx |
| ????setattr?? | 屬性賦值 | a.xxx = value |
| ????getitem?? | 索引運算 | a[key] |
| ????setitem?? | 索引賦值 | a[key]=value |
| ????len?? | 長度 | len(a) |
每個運算符實際上都對應了相應的方法,統計如下:
| 運算符 | 特殊方法 | 說明 |
| 運算符+ | ????add?? | 加法 |
| 運算符- | ????sub?? | 減法 |
| <,<=,== | ????lt?, le?,?eq?? | 比較運算符 |
| >,>=,!= | ????gt?, ge?, ne?? | |
| |,^,& | ????or?, xor?, and?? | 或、異或、與 |
119.特殊屬性
Python 對象中包含了很多雙下劃線開始和結束的屬性,這些是特殊屬性,有特殊用法。這里我們列出常見的特殊屬性:
| 特殊方法 | 含義 |
| obj.? ? dict? ?? | 對象的屬性字典 |
| obj.? ??class? ? | 對象所屬的類 |
| class.? ??bases? ?? | 類的基類元組(多繼承) |
| class.? ??base? ? ? | 類的基類 |
| class.? ??mro? ?? | 類層次結構 |
| class.? ??subclasses? ??() | 子類列表 |
120.對象的淺拷貝和深拷貝_內存分析
變量的賦值操作
只是形成兩個變量,實際還是指向同一個對象。
淺拷貝
Python 拷貝一般都是淺拷貝。拷貝時,對象包含的子對象內容不拷貝。因此,源對象和拷貝對象會引用同一個子對象。
深拷貝
使用 copy?模塊的 deepcopy?函數,遞歸拷貝對象中包含的子對象。源對象和拷貝對象所有的子對象也不同。
import copyclass MobilePhone:def __init__(self,cpu,screen): self.cpu = cpuself.screen = screenclass CPU:def calculate(self):print("計算,算個 12345")print("CPU 對象:",self)class Screen:def show(self):print("顯示一個好看的畫面,亮瞎你的鈦合金大眼")print("屏幕對象:",self)c = CPU() s = Screen() m1= MobilePhone(c,s)#測試淺復制 m2 = copy.copy(m1) print(m1,m1.cpu,m1.screen) print(m2,m2.cpu,m2.screen)#測試深復制 m3 = copy.deepcopy(m1) print(m1,m1.cpu,m1.screen) print(m3,m3.cpu,m3.screen) <__main__.MobilePhone object at 0x7fc88137d490> <__main__.CPU object at 0x7fc83801b730> <__main__.Screen object at 0x7fc83801b6d0> <__main__.MobilePhone object at 0x7fc83801bd90> <__main__.CPU object at 0x7fc83801b730> <__main__.Screen object at 0x7fc83801b6d0><__main__.MobilePhone object at 0x7fc88137d490> <__main__.CPU object at 0x7fc83801b730> <__main__.Screen object at 0x7fc83801b6d0> <__main__.MobilePhone object at 0x7fc83801bee0> <__main__.CPU object at 0x7fc881397a60> <__main__.Screen object at 0x7fc868050e80>121.組合
“is-a”關系,我們可以使用“繼承”。從而實現子類擁有的父類的方法和屬性。“is-a” 關系指的是類似這樣的關系:狗是動物,dog is animal。狗類就應該繼承動物類。
“has-a”關系,我們可以使用“組合”,也能實現一個類擁有另一個類的方法和屬性。” has-a”關系指的是這樣的關系:手機擁有 CPU。 MobilePhone has a CPU。
#繼承 class A1:def say_a1(self):print("a1,a1,a1") class B1(A1):pass b1=B1() b1.say_a1()#組合 class A2:def say_a2(self):print("a2,a2,a2") class B2:def __init__(self,a):self.a=a a2=A2() b2=B2(a2) b2.a.say_a2()122.設計模式_工廠模式實現
設計模式是面向對象語言特有的內容,是我們在面臨某一類問題時候固定的做法,設計模式有很多種,比較流行的是:GOF(Goup Of Four)23 種設計模式。當然,我們沒有必要全部學習,學習幾個常用的即可。
對于初學者,我們學習兩個最常用的模式:工廠模式和單例模式。
工廠模式實現了創建者和調用者的分離,使用專門的工廠類將選擇實現類、創建對象進行統一的管理和控制。
class CarFactory:def create_Car(self,brand):if brand == "奔馳": return Benz()elif brand == "寶馬": return BMW()elif brand == '比亞迪': return BYD()else:return "未知品牌,無法創建" class Benz:pass class BMW:pass class BYD:pass factory = CarFactory() c1 = factory.create_Car("奔馳") c2 = factory.create_Car("寶馬") print(c1) print(c2) <__main__.Benz object at 0x7fc898342250> <__main__.BMW object at 0x7fc898342c70>123.設計模式_單例模式實現
單例模式(Singleton Pattern)的核心作用是確保一個類只有一個實例,并且提供一個訪問該實例的全局訪問點。
單例模式只生成一個實例對象,減少了對系統資源的開銷。當一個對象的產生需要比較多的資源,如讀取配置文件、產生其他依賴對象時,可以產生一個“單例對象”,然后永久駐留內存中,從而極大的降低開銷。
#單例模式 class MySingleton:__obj = None__init_flag = Truedef __new__(cls, *args, **kwargs): if cls.__obj == None:cls.__obj = object.__new__(cls) return cls.__objdef __init__(self,name):if MySingleton.__init_flag: print("init")self.name = nameMySingleton.__init_flag = Falsea = MySingleton("aa") b = MySingleton("bb") print(a) print(b) init <__main__.MySingleton object at 0x7fa9a8febeb0> <__main__.MySingleton object at 0x7fa9a8febeb0>總結
以上是生活随笔為你收集整理的Python基础知识(第八天)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python基础知识(第七天)
- 下一篇: Python基础知识(第九天)