類的一些理論概念及其應(yīng)用場(chǎng)景等基礎(chǔ)內(nèi)容此處不贅述
目錄
python中一切皆對(duì)象
類的定義及基礎(chǔ)
屬性
方法
初始化方法
?普通方法
類之間的關(guān)系
相互調(diào)用
依賴關(guān)系
關(guān)聯(lián)關(guān)系
組合關(guān)系
三大特征----類的繼承
重寫父類方法
多繼承
混合繼承?
三大特征----封裝
三大特征----多態(tài)
isinstance?
抽象基類@abstractmethod
python中一切皆對(duì)象
python所有的數(shù)據(jù)類型都是對(duì)象,例如下面的a是int類的對(duì)象,b是str類的對(duì)象
a = 1
b = 'asc'
print(type(a))
print(type(b))
# <class 'int'>
# <class 'str'>
?而type創(chuàng)建了所有的類
class person:
pass
print(type(int))
print(type(str))
print(type(list))
print(type(dict))
print(type(person))
# <class 'type'>
# <class 'type'>
# <class 'type'>
# <class 'type'>
# <class 'type'>
??所有類的的基類都是? object?
print(int.__bases__)
print(str.__bases__)
print(list.__bases__)
print(dict.__bases__)
# (<class 'object'>,)
# (<class 'object'>,)
# (<class 'object'>,)
# (<class 'object'>,)
??object是被type創(chuàng)建的,而type類的基類是object(type創(chuàng)建object的同時(shí)也繼承了object)
print(type(object))
print(type.__bases__)
# <class 'type'>
# (<class 'object'>,)
類的定義及基礎(chǔ)
類的一般定義:
class Name_of_Class:
Shared_property=1
def __init__(self):
private_property=2
def method(self):
print(1)
類里包含了屬性和方法
屬性
屬性分為公共屬性和實(shí)例屬性,上面的shared_property就是共有屬性,private_property就是實(shí)例屬性,區(qū)別在于:
公有屬性是放在原始類的內(nèi)存中的,如果發(fā)生改變,所有對(duì)象都會(huì)發(fā)生改變
私有屬性是放在對(duì)象內(nèi)存中的,如果改變只會(huì)改變?cè)搶?duì)象的值,是對(duì)象獨(dú)享的
舉個(gè)例子
class Name_of_Class:
Shared_property=1
def __init__(self):
self.object_property=2
obj1=Name_of_Class()
obj2=Name_of_Class()
Name_of_Class.Shared_property=111
print(obj1.Shared_property)
print(obj2.Shared_property)
obj1.object_property=3
print(obj2.object_property)
# 111
# 111
# 2
那比如要設(shè)置一個(gè)? 某個(gè)年級(jí)學(xué)生信息的類,就可以把 年級(jí) 作為公共屬性,把一些身高體重等作為實(shí)例屬性
但是如果對(duì)象把類的公共屬性給改了,就相當(dāng)于給對(duì)象創(chuàng)建了一個(gè)新的實(shí)例有屬性
class Name_of_Class:
Shared_property=1
obj1=Name_of_Class()
obj2=Name_of_Class()
obj1.Shared_property=111
print(obj1.Shared_property)
print(obj2.Shared_property)
# 111
# 1
方法
初始化方法
def __init__(self):
pass
又叫做構(gòu)造方法,構(gòu)造函數(shù),實(shí)例化的時(shí)候會(huì)自動(dòng)運(yùn)行
初始化方法可以設(shè)置參數(shù),一般的格式是
class Name_of_Class:
Shared_property=1
def __init__(self,object_property1,object_property2):
self.object_property1=object_property1
self.object_property2=object_property2
調(diào)用方式是
obj1=Name_of_Class(2,3)
print(obj1.object_property1)
print(obj1.object_property2)
# 2
# 3
在進(jìn)行實(shí)例化的時(shí)候直接傳參就可以調(diào)用初始化方法
這里的self.object_property1=object_property1是確保將傳進(jìn)來(lái)的參數(shù)作為對(duì)象本身的實(shí)例屬性保存起來(lái),這里借用一張內(nèi)存圖說(shuō)明
- ?實(shí)例化時(shí),申請(qǐng)一塊內(nèi)存空間
- 將實(shí)例化的參數(shù)傳給__init__
- __init__將參數(shù)轉(zhuǎn)為實(shí)例屬性傳給這個(gè)內(nèi)存空間
?普通方法
class Name_of_Class:
Shared_property=1
def __init__(self,object_property1,object_property2):
self.object_property1=object_property1
self.object_property2=object_property2
def method(self):
print(self.object_property2+self.object_property1)
obj1=Name_of_Class(2,3)
obj1.method()
# 5
普通方法的參數(shù)同一有? self ,告知是哪個(gè)對(duì)象調(diào)用了方法
在普通方法中調(diào)用私有參數(shù)要? self.xxxx
類之間的關(guān)系
相互調(diào)用
只需要在定義類方法的時(shí)候?qū)⑵渌膶?duì)象作為參數(shù)傳進(jìn)去
class soilder:
def __init__(self,name,m4):
self.name=name
self.m4=m4
self.bloodall=100
def attack_back(self,badperson):
badperson.bloodall-=self.m4
print('soilder [%s] attack badperson [%s],badperson has [%s] blood'%(self.name,badperson.name,badperson.bloodall))
class badperson:
def __init__(self, name, ak):
self.name = name
self.ak = ak
self.bloodall = 100
def attack(self, soilder):
soilder.bloodall -= self.ak
print('badperson [%s] attack soilder [%s],soilder has [%s] blood'%(self.name,soilder.name,soilder.bloodall))
lee = soilder('lee',30)
liu =badperson('liu',35)
liu.attack(lee)
lee.attack_back(liu)
# badperson [liu] attack soilder [lee],soilder has [65] blood
# soilder [lee] attack badperson [liu],badperson has [70] blood
依賴關(guān)系
在依賴類的 初始化函數(shù) 中將master對(duì)象引入
class dog:
def __init__(self,name,age,master):
self.name=name
self.age=age
self.master=master
def say(self):
print('my master is ',self.master.name)
class master:
def __init__(self, name, age):
self.name = name
self.age = age
p1 = master('lee',23)
d1=dog('hhh',2,p1)
d1.say()
關(guān)聯(lián)關(guān)系
這個(gè)通過(guò)一個(gè)例子來(lái)說(shuō)明這種關(guān)系,生活中最常見(jiàn)的這種關(guān)系是? 結(jié)婚
結(jié)婚是兩個(gè)人一起結(jié)婚的,所以在這里最好定義一個(gè)新的類relationship來(lái)存儲(chǔ)兩個(gè)人的婚姻關(guān)系,這樣可以保證避免了A和B結(jié)婚了但是B和A沒(méi)結(jié)婚的bug出現(xiàn)
如果結(jié)婚了就調(diào)用get_marred函數(shù),如果離婚就是diverse函數(shù),狀態(tài)存儲(chǔ)在couple數(shù)組里面
person類中調(diào)用這個(gè)relation類進(jìn)行操作,并且可以通過(guò)get_partner函數(shù)獲取自己的伴侶
class relationship:
def __init__(self):
self.couple=[]
def get_married(self,obj1,obj2):
self.couple=[obj1,obj2]
print(obj1.name,'and ',obj2.name,'get married')
def diverse(self):
self.couple=[]
class person:
def __init__(self,name,age,sex,relation):
self.name=name
self.age=age
self.sex=sex
self.relation=relation
def get_partner(self):
for i in self.relation.couple:
if i.name==self.name:
continue
else:
return i.name
relationship_obj=relationship()
p1=person('lee',23,'M',relationship_obj)
p2=person('liu',22,'F',relationship_obj)
relationship_obj.get_married(p1,p2)
print(p2.get_partner())
relationship_obj.diverse()
print(p1.get_partner())
# lee and liu get married
# lee
# None
組合關(guān)系
由一堆組件構(gòu)成一個(gè)整體,組件自己獨(dú)立但是不能自己運(yùn)行,必須跟宿主結(jié)合,例如人的器官和人的關(guān)系
這里定義了一個(gè)器官類,里面有不同器官的函數(shù)
在定義person類時(shí),直接?self.action=organs(),既實(shí)例化一個(gè)器官對(duì)象,那么每次實(shí)例化一個(gè)person都會(huì)實(shí)例化一個(gè)organs,器官和人就是組合關(guān)系
class organs:
def __init__(self):
self.name=None
def heart(self):
self.name = '心臟'
print('心臟跳動(dòng)了一下')
def lung(self):
self.name='肺'
print('肺呼吸了一下')
class person:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
self.action=organs()
def get_partner(self):
for i in self.relation.couple:
if i.name==self.name:
continue
else:
return i.name
p1=person('lee',23,'M')
p2=person('liu',22,'F')
p1.action.heart()
p1.action.lung()
# 心臟跳動(dòng)了一下
# 肺呼吸了一下
三大特征----類的繼承
類的繼承是三大特征之一,主要的功能是使類A能得到類B的所有方法和屬性而不需要重復(fù)書寫代碼,繼承的方式就是在定義的時(shí)候加入父類的名字:
class son(father):
pass
例如豬和人都是動(dòng)物,那么可以抽象一個(gè)animal類,把動(dòng)物該有的屬性和方法加入,當(dāng)然新定義的類也可以加入自己獨(dú)有的方法,或者重構(gòu) 原有父類的方法:
class animal:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def eat(self):
print(111)
class pig(animal):
pass
class person(animal):
def eat(self):
print(333)
def thinking(self):
print(222)
p1 = pig('liu',2,'M')
p2 = person('lee',23,'F')
p1.eat()
p2.thinking()
p2.eat()
# 111
# 222
# 333
重寫父類方法
新定義的類也可以在原有類的基礎(chǔ)上增加功能,而不完全重構(gòu)
下面的代碼在person繼承了animal類,并且增加了初始化函數(shù)和普通方法的功能,主要思想就是在定義新的類的方法使,先運(yùn)行父類的方法
class animal:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def eat(self):
print(111)
class person(animal):
def __init__(self,name,age,sex,hobby):
animal.__init__(self,name,age,sex)
self.hobby=hobby
def eat(self):
animal.eat(self)
print(333)
def thinking(self):
print(222)
p2 = person('lee',23,'F','study')
print(p2.hobby)
p2.eat()
# study
# 111
# 333
在高版本的python中,還支持這種寫法,其實(shí)結(jié)果是一樣的:
class person(animal):
def __init__(self,name,age,sex,hobby):
super(person,self).__init__(name,age,sex)
# animal.__init__(self,name,age,sex)
self.hobby=hobby
def eat(self):
super(person, self).eat()
print(333)
def thinking(self):
print(222)
或者
class person(animal):
def __init__(self,name,age,sex,hobby):
super().__init__(name,age,sex)
# animal.__init__(self,name,age,sex)
self.hobby=hobby
def eat(self):
super().eat()
print(333)
def thinking(self):
print(222)
多繼承
?python是允許多繼承的,也就是可以同時(shí)繼承多個(gè)父類
當(dāng)父類也有父類時(shí),就有一個(gè)樹(shù)狀結(jié)構(gòu),此時(shí)繼承順序就很重要,這里有一個(gè)簡(jiǎn)單的例子
例如下面這種情況,同時(shí)繼承了兩個(gè)類,按照從左到右的順序繼承
class father(grandpa):
def test(self):
print('father')
class mother:
def test(self):
print('mother')
class son(father,mother):
pass
p1=son()
p1.test()
#fatehr
再例如,當(dāng)father類沒(méi)有test時(shí),會(huì)搜索father的父輩grandpa:
class grandpa:
def test(self):
print('grandpa')
class father(grandpa):
pass
class mother:
def test(self):
print('mother')
class son(father,mother):
pass
p1=son()
p1.test()
#grandpa
到這里為止,都很像深度優(yōu)先搜索,但是其實(shí)不是,而是運(yùn)用了C3算法,比如當(dāng)fater和mather類都繼承自grandpa時(shí):
class grandpa:
def test(self):
print('grandpa')
class father(grandpa):
pass
class mother(grandpa):
def test(self):
print('mother')
class son(father,mother):
pass
p1=son()
p1.test()
# mother
為了方便,可以直接查看類的繼承順序
print(son.mro())
#[<class '__main__.son'>, <class '__main__.father'>, <class '__main__.mother'>, <class #'__main__.grandpa'>, <class 'object'>]
至于C3算法,有興趣的可以看看這個(gè)?
Python 中多繼承 C3-MRO 算法的剖析 - 知乎
混合繼承?
當(dāng)一個(gè)類bird繼承了多個(gè)子類時(shí),子類之間的方法可以直接調(diào)用,也能調(diào)用到最初始子類(annimal)的私有屬性
class animal():
def __init__(self,name):
self.name = name
class Fly():
def fly(self):
print(f'{self.name} fly')
class Swim():
def swim(self):
print(f'{self.name} swim')
class Run():
def run(self):
print(f'{self.name} run')
class Bird(animal,Fly,Swim,Run):
pass
bird = Bird('lmx')
bird.fly()
bird.swim()
bird.run()
# lmx fly
# lmx swim
# lmx run
?像上述Fly、Swim、Run這種類功能簡(jiǎn)單,易于維護(hù),一般稱為mixin
一般來(lái)說(shuō),mixin功能是單一的,且不能繼承別的類
在使用mixin時(shí)盡量避免使用super
三大特征----封裝
封裝可以被認(rèn)為是一個(gè)保護(hù)屏障,防止該類的代碼和數(shù)據(jù)被外部類定義的代碼隨機(jī)訪問(wèn)。
要訪問(wèn)該類的代碼和數(shù)據(jù),必須通過(guò)嚴(yán)格的接口控制。
封裝最主要的功能在于我們能修改自己的實(shí)現(xiàn)代碼,而不用修改那些調(diào)用我們代碼的程序片段。
適當(dāng)?shù)姆庋b可以讓程式碼更容易理解與維護(hù),也加強(qiáng)了代碼數(shù)據(jù)的安全性。
比如一個(gè)這樣的例子,人在銀行的財(cái)產(chǎn)只能通過(guò)一些方法改變,例如存錢和取錢,如果按照普通的定義:
class person_bank:
def __init__(self,name):
self.money=0
p1=person_bank('lee')
p1.money=100
print(p1.money)
# 100
這樣其實(shí)是不安全的,因?yàn)橥獠空l(shuí)都可以自由的修改money的值
?這里引入私有屬性的概念,其實(shí)就是使得外部不能訪問(wèn),但是在類里面是可以訪問(wèn)的,只需要在變量前加 __
class person_bank:
def __init__(self,name):
self.__money=0
def get_money(self,num):
self.__money=self.__money+num
def check(self):
print(self.__money)
p1=person_bank('lee')
p1.check()
p1.get_money(100)
p1.check()
# 0
# 100
那么將私有屬性放入類方法中修改的這種模式就叫做封裝
當(dāng)然方法也可以變?yōu)樗接蟹椒?/p>
class person_bank:
def __init__(self,name):
self.__money=0
def __interest(self):
self.__money=self.__money+1
p1=person_bank('lee')
p1.__interest()
# 'person_bank' object has no attribute '__interest'
但是其實(shí)私有屬性和方法也不是完全不能外部訪問(wèn)的,也可以用下面這種方法破解
也就是? 實(shí)例名._類名+方法名
print(p1._person_bank__money)
p1._person_bank__interest()
三大特征----多態(tài)
有時(shí)一個(gè)對(duì)象會(huì)有多種表現(xiàn)形式,比如網(wǎng)站頁(yè)面有個(gè)button按鈕,這個(gè)button的設(shè)計(jì)可以不一樣(單選框、多選框、圓角的點(diǎn)擊按鈕、直角的點(diǎn)擊按鈕等),盡管長(zhǎng)的不一樣,但它們都有一個(gè)共同調(diào)用方式,就是onClick()方法。我們直要在頁(yè)面上一點(diǎn)擊就會(huì)觸發(fā)這個(gè)方法。點(diǎn)完后有的按鈕會(huì)變成選中狀態(tài)、有的會(huì)提交表單、有的甚至?xí)棿?。這種多個(gè)對(duì)象共用同一個(gè)接口,又表現(xiàn)的形態(tài)不一樣的現(xiàn)象,就叫做多態(tài)( Polymorphism )。
通過(guò)統(tǒng)一接口實(shí)現(xiàn)多態(tài):
其實(shí)就是封裝一個(gè)函數(shù),調(diào)用不同類的同名方法
class one:
def test(self):
print(1)
class two:
def test(self):
print(2)
def gettest(obj):
obj.test()
a=one()
b=two()
gettest(a)
gettest(b)
通過(guò)抽象類實(shí)現(xiàn)多態(tài)
class num:
def test(self):
# 可以繼承,但是必須自己定義一個(gè)新的
raise NotImplementedError('自己定義')
class one(num):
def test(self):
print(1)
class two(num):
def test(self):
print(2)
a=one()
b=two()
objs=[a,b]
for i in objs:
i.test()
isinstance?
用于判斷傳入對(duì)象是否是指定的類型
class father():
pass
class son(father):
pass
a = son()
print(isinstance(a,father))
print(isinstance(a,son))
# True
# True
一些其他的方法無(wú)法做到判斷父類,例如
print(type(a)==son)
print(type(a)==father)
print(type(a) is son)
print(type(a) is father)
# True
# False
# True
# False
?==是對(duì)值的判斷,is是對(duì)地址的判斷,無(wú)法判斷父類
抽象基類@abstractmethod
**抽象方法(Abstract Methods)**:抽象基類定義了一組抽象方法,這些方法在基類中沒(méi)有實(shí)現(xiàn)任何功能,只有方法簽名(名稱和參數(shù)),通常使用`@abstractmethod`裝飾器來(lái)標(biāo)記這些方法。子類必須實(shí)現(xiàn)這些抽象方法。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-686616.html
from abc import ABC, abstractmethod
class Cache(ABC):
@abstractmethod
def get_cache(self):
pass
@abstractmethod
def set_cache(self):
pass
class get_cache(Cache):
pass
class read_cache(Cache):
def get_cache(self):
print(1)
def set_cache(self):
print(2)
a = get_cache()
# TypeError: Can't instantiate abstract class get_cache with abstract methods get_cache, set_cache
b = read_cache()
b.get_cache()
# 1
例如上面這個(gè)例子,Cache就是抽象基類,他的子類必須重構(gòu) get_cache和 set_cache這兩個(gè)方法才能被實(shí)例化文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-686616.html
到了這里,關(guān)于Python面向?qū)ο缶幊蹋ㄒ唬╊惖幕A(chǔ),關(guān)系,繼承,封裝,多態(tài)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!