一逐沙、多態(tài)
1.概念
一種事物的多種體現(xiàn)形式偏序,函數(shù)的重寫(xiě)其實(shí)就是多態(tài)的一種體現(xiàn)
在Python中哼御,多態(tài)指的是父類的引用指向子類的對(duì)象
代碼演示:
#父類 class Animal(object): pass #子類 class Dog(Animal): pass class Cat(Animal): pass #定義變量 a = [] #a是list類型 b = Animal() #b是Animal類型 c = Cat() #c是Cat類型 #isinstance():判斷一個(gè)對(duì)象是否屬于某種類型【系統(tǒng)還是自定義的類型】 print(isinstance(a,list)) print(isinstance(b,Animal)) print(isinstance(c,Cat)) print(isinstance(c,Animal)) #True print(isinstance(b,Dog)) #False #結(jié)論:子類對(duì)象可以是父類類型,但是兰粉,父類的對(duì)象不能是子類類型
2.使用
案例:人可以喂貓故痊,喂狗
思路:
a.定義動(dòng)物類【父類】
b.定義子類,繼承自動(dòng)物類
c.定義人類
d.使用多態(tài)玖姑,優(yōu)化
代碼演示:
duoTaiDemo.py文件
from duotai.person import Person from duotai.cat import Cat from duotai.dog import Dog #1.創(chuàng)建一個(gè)Person的對(duì)象 p = Person() #2.創(chuàng)建一個(gè)Cat的對(duì)象 c = Cat("小白") #3.人執(zhí)行自己的行為 p.feedAnimal(c) d = Dog("旺財(cái)") p.feedAnimal(d)
person.py文件
class Person(object): """ def feedCat(self,cat): print("喂貓:",cat.name) cat.eat() def feedDog(self,dog): print("喂貓:",dog.name) dog.eat() """ #多態(tài) #ani被當(dāng)做父類的引用 愕秫,當(dāng)傳參的時(shí)候,實(shí)參是一個(gè)子類對(duì)象的時(shí)候焰络,則體現(xiàn)出了 多態(tài)的應(yīng)用 def feedAnimal(self,ani): #ani = c c = Cat("") print("喂動(dòng)物:", ani.name) ani.eat()
animal.py文件
class Animal(object): def __init__(self,name): self.name = name def eat(self): print("eating")
cat.py文件
from duotai.animal import Animal class Cat(Animal): def __init__(self,name): super(Cat,self).__init__(name)
dog.py文件
from duotai.animal import Animal class Dog(Animal): def __init__(self,name): super(Dog,self).__init__(name)
總結(jié):
? 簡(jiǎn)化代碼戴甩,提高代碼的可讀性,可維護(hù)性
二舔琅、獲取對(duì)象信息
type() isintance() dir()
代碼演示:
#1.type() :判斷一個(gè)對(duì)象所屬的類型 num = 10 print(type(num)) print(type("hello")) class Check(object): pass c = Check() print(type(c)) #使用==判斷type返回的結(jié)果 print(type(12) == type(57)) #True print(type(12) == type("57")) #False #使用type返回的結(jié)果和數(shù)據(jù)類型直接判斷 print(type(12) == int) #2.isintance() :判斷一個(gè)對(duì)象是否屬于某種指定的數(shù)據(jù)類型 #自定義的類中 class Dog(object): pass d = Dog() print(isinstance(d,Dog)) print(isinstance([1,2,4],list)) #特殊用法:可以判斷一個(gè)對(duì)象是否屬于多種數(shù)據(jù)類型中的某一種 print(isinstance([1,2,4],(tuple,list))) #3.dir() :列出指定對(duì)象中所包含的所有的內(nèi)容【成員變量等恐,成員方法】 dict = {} print(dir(dict)) print(dir("abc")) print(dir(d))
三洲劣、類中特殊的屬性和方法
1.實(shí)例屬性和類屬性
1.1實(shí)例屬性和類屬性的區(qū)別【面試題】
a.定義的位置不同备蚓,類屬性時(shí)直接定義在類中课蔬,實(shí)例屬性定義在構(gòu)造函數(shù)中
b.訪問(wèn)的方式不同,類屬性使用類名直接訪問(wèn)郊尝,實(shí)例屬性使用對(duì)象訪問(wèn)
c.在內(nèi)存中出現(xiàn)的時(shí)機(jī)不同二跋,類屬性隨著類的出現(xiàn)而出現(xiàn),實(shí)例屬性隨著對(duì)象的出現(xiàn)而出現(xiàn)
d.優(yōu)先級(jí)不同流昏,實(shí)例屬性的優(yōu)先級(jí)高于類屬性
代碼演示:
class Person(object): #1.定義位置 #類屬性:直接定義在類中 name = "abc" age = 0 def __init__(self,name): #實(shí)例屬性:定義在構(gòu)造函數(shù)中 self.name = name #2.訪問(wèn)方式 print(Person.name) #類屬性:類名.屬性 或者 對(duì)象.屬性 p = Person("hello") print(p.name) #實(shí)例屬性:對(duì)象.屬性 #3.優(yōu)先級(jí)不同:實(shí)例屬性的優(yōu)先級(jí)高于類屬性 print(p.name) #hello #4.不同對(duì)象的類屬性在內(nèi)存中是不是同一塊空間扎即?----->不是 p1 = Person("小白") p2 = Person("小紅") print(p1.age) print(p2.age) p1.age = 33 print(p1.age) print(p2.age) print(id(p1.age)) print(id(p2.age)) """ 0 0 33 0 1420404832 1420403776 """ #注意:盡量避免類屬性和實(shí)例屬性的重名 #刪除屬性【類屬性,實(shí)例屬性】 del p1.age
1.2動(dòng)態(tài)添加屬性和方法
代碼演示:
from types import MethodType class Person(object): #__slots__ = ("name","age") pass #1.動(dòng)態(tài)添加屬性 per = Person() str = "fjsgh" per.name = str #2.動(dòng)態(tài)添加方法 def say(self): print("fhsj") """ per.test = say per.test(per) """ #弊端:違背了普通函數(shù)定義 #解決方案:MethodType類况凉,存在于types模塊下 #類似于偏函數(shù) #參數(shù):函數(shù)名谚鄙,對(duì)象 #作用:在現(xiàn)有函數(shù)的基礎(chǔ)上生成了一個(gè)對(duì)象【新的函數(shù)】,賦值給成員變量刁绒,則認(rèn)為給對(duì)象添加了一個(gè)成員方法 per.test = MethodType(say,per) per.test()
2.類方法和靜態(tài)方法
類方法:使用@classmethod裝飾器修飾的方法闷营,被稱為類方法,可以通過(guò)類名調(diào)用知市,也可以通過(guò)對(duì)象調(diào)用傻盟,但是一般情況下使用類名調(diào)用
靜態(tài)方法:使用@staticmethod裝飾器修飾的方法,被稱為靜態(tài)方法嫂丙,可以通過(guò)類名調(diào)用娘赴,也可以通過(guò)對(duì)象調(diào)用,但是一般情況下使用類名調(diào)用
代碼演示:
class Test(object): #1.類屬性 age = 100 def __init__(self,name): #2.實(shí)例屬性 self.name = name #3.成員方法,通過(guò)對(duì)象調(diào)用 #必須有一個(gè)參數(shù)跟啤,這個(gè)參數(shù)一般情況下為self诽表,self代表是當(dāng)前對(duì)象 def func(self): print("func") #4.類方法 """ a.必須有一個(gè)參數(shù),這個(gè)參數(shù)一般情況下為cls隅肥,cls代表的是當(dāng)前類 b.類方法是屬于整個(gè)類的关顷,并不是屬于某個(gè)具體的對(duì)象,在類方法中禁止出現(xiàn)self c.在類方法的內(nèi)部武福,可以直接通過(guò)cls調(diào)用當(dāng)前類中的屬性和方法 d.在類方法的內(nèi)部议双,可以通過(guò)cls創(chuàng)建對(duì)象 """ @classmethod def test(cls): print("類方法") print(cls) #<class 'methodDemo01.Test'> print(cls.age) #6 #注意:cls完全當(dāng)做當(dāng)前類使用 c = cls("hello") c.func() #7.靜態(tài)方法 @staticmethod def show(): print("靜態(tài)方法") t = Test("hjfsh") t.func() #5,.調(diào)用類方法 Test.test() #類名.類方法的名稱() t.test() #對(duì)象.類方法的名稱() #7。調(diào)用靜態(tài)方法 Test.show() t.show()
總結(jié):實(shí)例方法【成員方法】捉片、類方法以及靜態(tài)方法之間的區(qū)別
a.語(yǔ)法上
? 實(shí)例方法:第一個(gè)參數(shù)一般為self平痰,在調(diào)用的時(shí)候不需要傳參,代表的是當(dāng)前對(duì)象【實(shí)例】
? 靜態(tài)方法:沒(méi)有特殊要求
? 類方法:第一個(gè)參數(shù)必須為cls伍纫,代表的是當(dāng)前類
b.在調(diào)用上
? 實(shí)例方法:只能對(duì)象
? 靜態(tài)方法:對(duì)象 或者 類
? 類方法:對(duì)象 或者 類
c.在繼承上【相同點(diǎn)】
? 實(shí)例方法宗雇、靜態(tài)方法、類方法:當(dāng)子類中出現(xiàn)和父類中重名的函數(shù)的時(shí)候莹规,子類對(duì)象調(diào)用的是子類中的方法【重寫(xiě)】
代碼演示:
class SuperClass(object): @staticmethod def show(): print("父類中的靜態(tài)方法") @classmethod def check(cls): print("父類中的類方法") class SubClass(SuperClass): pass s = SubClass() s.show() s.check()
注意:注意區(qū)分三種函數(shù)的書(shū)寫(xiě)形式赔蒲,在使用,沒(méi)有絕對(duì)的區(qū)分
3.類常用屬性
__name__ 通過(guò)類名訪問(wèn),獲取類名字符串 不能通過(guò)對(duì)象訪問(wèn)舞虱,否則報(bào)錯(cuò) __dict__ 通過(guò)類名訪問(wèn)欢际,獲取指定類的信息【類方法,靜態(tài)方法矾兜,成員方法】损趋,返回的是一個(gè)字典 通過(guò)對(duì)象訪問(wèn),獲取的該對(duì)象的信息【所有的屬性和值】椅寺,浑槽,返回的是一個(gè)字典 __bases__ 通過(guò)類名訪問(wèn),查看指定類的所有的父類【基類】
代碼演示:
class Animal(object): def __init__(self,arg): super(Animal, self).__init__() self.arg = arg class Tiger(Animal): age = 100 height = 200 def __init__(self,name): #super(Tiger, self).__init__(name) self.name = name def haha(self): print("haha") @classmethod def test(cls): print("cls") @staticmethod def show(): print("show") if __name__ == "__main__": #1.__name__ print(Tiger.__name__) #Tiger t = Tiger("") #print(t.__name__) #AttributeError: 'Tiger' object has no attribute '__name__' #2.__dict__ print(Tiger.__dict__) #類屬性返帕,所有的方法 print(t.__dict__) #實(shí)例屬性 #3.__bases__桐玻,獲取指定類的所有的父類,返回的是一個(gè)元組 print(Tiger.__bases__)
四荆萤、運(yùn)算符重載【了解】
運(yùn)算符重載其實(shí)就是函數(shù)重寫(xiě)
代碼演示:
print(1 + 1) print("1" + "1") #print("1" + 1) #不同的數(shù)據(jù)類型進(jìn)行加法運(yùn)算得到的是不同的解釋 #思考問(wèn)題:兩個(gè)對(duì)象相加畸冲? class Person(object): def __init__(self,num): self.num = num def __str__(self): return "num=" + str(self.num) def __add__(self, other): #兩個(gè)對(duì)象相加得到的結(jié)果仍然為一個(gè)對(duì)象 return Person(self.num + other.num) #Peson(30) p1 = Person(10) p2 = Person(20) print(p1) #10 print(p2) #20 print(p1 + p2) #30 #p1 + p2----->p1.__add__(p2),
五、單例設(shè)計(jì)模式【擴(kuò)展】
1.概念
什么是設(shè)計(jì)模式
? 經(jīng)過(guò)已經(jīng)總結(jié)好的解決問(wèn)題的方案
? 23種設(shè)計(jì)模式观腊,比較常用的是單例設(shè)計(jì)模式邑闲,工廠設(shè)計(jì)模式,代理模式梧油,裝飾模式
什么是單例設(shè)計(jì)模式
? 單個(gè)實(shí)例【對(duì)象】
? 在程序運(yùn)行的過(guò)程中苫耸,確保某一個(gè)類只能有一個(gè)實(shí)例【對(duì)象】,不管在哪個(gè)模塊中獲取對(duì)象儡陨,獲取到的都是同一個(gè)對(duì)象
? 單例設(shè)計(jì)模式的核心:一個(gè)類有且僅有一個(gè)實(shí)例褪子,并且這個(gè)實(shí)例需要應(yīng)用在整個(gè)工程中
2.應(yīng)用場(chǎng)景
實(shí)際應(yīng)用:數(shù)據(jù)庫(kù)連接池操作-----》應(yīng)用程序中多處需要連接到數(shù)據(jù)庫(kù)------》只需要?jiǎng)?chuàng)建一個(gè)連接池即可,避免資源的浪費(fèi)
3.實(shí)現(xiàn)
3.1模塊
Python的模塊就是天然的單例設(shè)計(jì)模式
模塊的工作原理:
? import xxx,模塊被第一次導(dǎo)入的時(shí)候骗村,會(huì)生成一個(gè).pyc文件嫌褪,當(dāng)?shù)诙螌?dǎo)入的時(shí)候,會(huì)直接加載.pyc文件胚股,將不會(huì)再去執(zhí)行模塊源代碼
3.2使用new【掌握】
__new__():實(shí)例從無(wú)到有的過(guò)程【對(duì)象的創(chuàng)建過(guò)程】
代碼演示:
class Singleton(object): #類屬性 instance = None #類方法 @classmethod def __new__(cls, *args, **kwargs): #如果instance的值不為None笼痛,說(shuō)明已經(jīng)被實(shí)例化了,則直接返回琅拌;如果為NOne缨伊,則需要被實(shí)例化 if not cls.instance: cls.instance = super(Singleton,cls).__new__(*args, **kwargs) return cls.instance class MyClass(Singleton): pass #當(dāng)創(chuàng)建對(duì)象的時(shí)候自動(dòng)被調(diào)用 one = MyClass() two = MyClass() print(id(one)) print(id(two)) print(one is two)
3.3裝飾器【掌握】
代碼演示:
#單例類:將裝飾器作用于一個(gè)類上 def singleton(cls): #類屬性 instance = {} #成員方法 def getSingleton(*args, **kwargs): #思路:如果cls在字典中,則直接返回进宝;如果不存在刻坊,則cls作為key,對(duì)象作為value党晋,添加到字典中 if cls not in instance: instance[cls] = cls(*args, **kwargs) return instance[cls] return getSingleton @singleton class Test(object): pass t1 = Test() t2 = Test() print(id(t1) == id(t2)) print(t1 is t2)
3.4使用在類中【掌握】
代碼演示:
#單例類 class Foo(object): #1.聲明一個(gè)變量【類屬性】 instance = None #2.向外界提供一個(gè)公開(kāi)的方法谭胚,用于返回當(dāng)前類唯一的對(duì)象 #方法命名格式:defaultInstance,currentInstance ,getInstance @classmethod def getInstance(cls): if cls.instance: return cls.instance else: #實(shí)例化 cls.instance = cls() return cls.instance obj1 = Foo.getInstance() obj2 = Foo.getInstance() print(id(obj1) == id(obj2)) print(obj1 is obj2)