Python——類夺颤、面向?qū)ο罅《校庋b 繼承 多態(tài)
面向過(guò)程:根據(jù)業(yè)務(wù)邏輯從上到下寫代碼
面向?qū)ο螅簩?shù)據(jù)與函數(shù)綁定到一起,進(jìn)行封裝世澜,這樣能夠更快速的開(kāi)發(fā)程序独旷,減少了重復(fù)代碼的重寫過(guò)程
類
人以類聚 物以群分。
具有相似內(nèi)部狀態(tài)和運(yùn)動(dòng)規(guī)律的實(shí)體的集合(或統(tǒng)稱為抽象)寥裂。
具有相同屬性和行為事物的統(tǒng)稱
類是抽象的,在使用的時(shí)候通常會(huì)找到這個(gè)類的一個(gè)具體的存在,使用這個(gè)具體的存在嵌洼。一個(gè)類可以找到多個(gè)對(duì)象
在Python中編寫類的方式如下:
class Dog():
'''創(chuàng)建小狗的類'''
def init(self,name,age):
self.name = name
self.age = age
'''動(dòng)作方法 play'''
def sit(self):
print('狗在玩')
方法init()
init()是一個(gè)特殊的方法,每當(dāng)根據(jù)類創(chuàng)建類的實(shí)例時(shí)封恰,Python都會(huì)自動(dòng)運(yùn)行這個(gè)方法麻养。在這個(gè)方法中開(kāi)頭和末尾各有兩個(gè)下劃線。
避免Python默認(rèn)方法與普通方法發(fā)生名稱沖突诺舔。
init()定義中我們傳遞了三個(gè)參數(shù):self鳖昌、name和age。這個(gè)初始化方法中self是必須的低飒。而且還必須位于其他的形參前面许昨。每個(gè)與類相關(guān)聯(lián)的方法調(diào)用都自動(dòng)傳遞實(shí)參self,它是一個(gè)指向?qū)嵗旧淼囊萌焐蕖W寣?shí)例能夠訪問(wèn)類中的屬性和方法
在init()方法中定義的兩個(gè)變量都有前綴self糕档。以self為前綴的變量都可供類中的所有方法使用。
init()沒(méi)有并沒(méi)有顯式地包含return語(yǔ)句拌喉,但Python自動(dòng)返回類對(duì)象的實(shí)例速那。
? init_()方法,在創(chuàng)建一個(gè)對(duì)象時(shí)默認(rèn)被調(diào)用尿背,不需要手動(dòng)調(diào)用
? init(self)中端仰,默認(rèn)有1個(gè)參數(shù)名字為self,如果在創(chuàng)建對(duì)象時(shí)傳遞了2個(gè)實(shí)參残家,那么init(self)中出了self作為第一個(gè)形參外還需要2個(gè)形參榆俺,例
? init(self,x,y)
init(self)中的self參數(shù),不需要開(kāi)發(fā)者傳遞坞淮,python解釋器會(huì)自動(dòng)把當(dāng)前的對(duì)象引用傳遞進(jìn)去*
Python3.0創(chuàng)建類的方法
?在Python3.0中創(chuàng)建類
class ClassName(Object):
pass
根據(jù)類創(chuàng)建實(shí)例
my_dog = Dog()
my_dog.play()
為屬性指定默認(rèn)值
類中的每個(gè)屬性指定默認(rèn)值茴晋。
class CarPro:
def init(self):
self.t=0
self.info='鐵皮'
self.SideDishes=[]
def str(self):
a=''
for i in self.SideDishes:
a+=i+','
a=a.strip(',')
return '現(xiàn)在加工的是%s,加工了%d分鐘'%(self.info,self.t)
def CarProduct(self,t1):
self.t+=t1
if self.t>=10:
self.info='汽車產(chǎn)生了'
elif self.t>=8:
self.info='汽車各個(gè)部件噴涂'
elif self.t>=6:
self.info='汽車各個(gè)部件涂膠'
elif self.t>=5:
self.info='汽車各個(gè)部位點(diǎn)焊,弧焊回窘,鉚焊'
else:
self.info='一堆鐵皮'
類的繼承
在程序中诺擅,繼承描述的是事物之間的所屬關(guān)系,例如貓和狗都屬于動(dòng)物啡直,程序中便可以描述為貓和狗繼承自動(dòng)物烁涌;同理苍碟,波斯貓和巴厘貓都繼承自貓,而沙皮狗和斑點(diǎn)狗都繼承足夠撮执。
?定義子類時(shí)微峰,必須在括號(hào)內(nèi)指定父類的名稱
?在創(chuàng)建子類的實(shí)例時(shí),Python首先需要給父類的所有屬性賦值抒钱。
?創(chuàng)建子類時(shí)蜓肆,父類必須包含在當(dāng)前文件中,且位于子類前面谋币。
?子類中可以使用super()代表父類的引用仗扬。
class Cat(object):
def init(self, name, color="白色"):
self.name = name
self.color = color
def run(self):
print("%s--在跑"%self.name)
定義一個(gè)子類,繼承Cat類如下:
class Bosi(Cat):
def setNewName(self, newName):
self.name = newName
def eat(self):
print("%s--在吃"%self.name)
bs = Bosi("印度貓")
print('bs的名字為:%s'%bs.name)
print('bs的顏色為:%s'%bs.color)
bs.eat()
bs.setNewName('波斯')
bs.run()
類——object
每一個(gè)python類都隱含了一個(gè)超類:object蕾额,這個(gè)類是一個(gè)非常簡(jiǎn)單的定義早芭,這個(gè)類幾乎不做任何事情。
重寫诅蝶、調(diào)用父類方法
?所謂重寫退个,就是子類中,有一個(gè)和父類相同名字的方法秤涩,在子類中的方法會(huì)覆蓋掉父類中同名的方法
看幾個(gè)栗子
class Cat(object):
def sayHello(self):
print("halou-----1")
class Bosi(Cat):
def sayHello(self):
print("halou-----2")
bosi = Bosi()
bosi.sayHello()
<main.son object at 0x101a45908>
class Cat(object):
def init(self,name):
self.name = name
self.color = 'yellow'
class Bosi(Cat):
def init(self,name):
# 調(diào)用父類的init方法1(python2)
#Cat.init(self,name)
# 調(diào)用父類的init方法2
#super(Bosi,self).init(name)
# 調(diào)用父類的init方法3
super().init(name)
def getName(self):
return self.name
bosi = Bosi('xiaohua')
print(bosi.name)
print(bosi.color)
多繼承
Python支持多繼承帜乞,我們知道子類會(huì)繼承父類中的屬性和方法。python中需要繼承多個(gè)類的時(shí)候筐眷,使用如下的格式
class 子類(父類1,父類2):
pass
那么當(dāng)多個(gè)父類都含有相同的方法习柠,會(huì)如何執(zhí)行呢匀谣?
class father1:
def say(self,args):
print(args+'father1')
class father2:
def say(self,args):
print(args+'father2')
class son(father1,father2):
pass
s = son()
s.say('it say something')
it say somethingfather1
可以看到,python會(huì)執(zhí)行第一個(gè)父類中的相關(guān)方法
我們用圖解來(lái)解釋一下執(zhí)行順序
142800ycssa7s7m00aac2t.png
定義一個(gè)父類
class A:
def printA(self):
print('----A----')
定義一個(gè)父類
class B:
def printB(self):
print('----B----')
定義一個(gè)子類资溃,繼承自A武翎、B
class C(A,B):
def printC(self):
print('----C----')
obj_C = C()
obj_C.printA()
obj_C.printB()
python中是可以多繼承的
父類中的方法、屬性溶锭,子類會(huì)繼承
我們根據(jù)執(zhí)行結(jié)果宝恶,可以看到程序會(huì)現(xiàn)在子類中查找要執(zhí)行的方法和函數(shù),然后會(huì)在第一個(gè)父類中尋找如果沒(méi)有找到趴捅,會(huì)在第二個(gè)父類中尋找垫毙。如果也沒(méi)有找到會(huì)去父類的公共基類找。
程序的執(zhí)行順序是 1 2 3
私有化
?如果有一個(gè)對(duì)象拱绑,當(dāng)需要對(duì)其進(jìn)行修改屬性時(shí)综芥,有2種方法
對(duì)象名.屬性名 = 數(shù)據(jù) ---->直接修改
對(duì)象名.方法名() ---->間接修改
?為了更好的保存屬性安全,即不能隨意修改猎拨,一般的處理方式為
將屬性定義為私有屬性
添加一個(gè)可以調(diào)用的方法膀藐,供調(diào)用
私有化.png
靜態(tài)方法和類方法
是類對(duì)象所擁有的方法屠阻,需要用修飾器@classmethod來(lái)標(biāo)識(shí)其為類方法,對(duì)于類方法额各,第一個(gè)參數(shù)必須是類對(duì)象国觉,一般以cls作為第一個(gè)參數(shù)(當(dāng)然可以用其他名稱的變量作為其第一個(gè)參數(shù),但是大部分人都習(xí)慣以’cls’作為第一個(gè)參數(shù)的名字虾啦,就最好用’cls’了)蛉加,能夠通過(guò)實(shí)例對(duì)象和類對(duì)象去訪問(wèn)。
?靜態(tài)字段的創(chuàng)建
class People(object):
country = 'china'
@staticmethod
#靜態(tài)方法
def getCountry():
return People.country
print (People.getCountry())
類方法
?調(diào)用get方法
test = duck('test123')
print(test.get_name)
?調(diào)用setter方法
test = duck('test123')
test.set_name = '123test'
print(test.get_name)
使用名稱重整保護(hù)私有特性
在前面的Duck例子中缸逃,如果直接訪問(wèn)hidden_name還是可以看到對(duì)應(yīng)屬性的值针饥。Python對(duì)那些需要可以隱藏在類內(nèi)部的特性有自己的命名規(guī)范:由連續(xù)的兩個(gè)下劃線開(kāi)頭(__)
class People(object):
country = 'china'
#類方法,用classmethod來(lái)進(jìn)行修飾
@classmethod
def getCountry(cls):
return cls.country
p = People()
print (p.getCountry()) #可以用過(guò)實(shí)例對(duì)象引用
print (People.getCountry()) #可以通過(guò)類對(duì)象引用
類方法還有一個(gè)用途就是可以對(duì)類屬性進(jìn)行修改:
對(duì)于父類的方法需频,只要它不符合子類的調(diào)用行為丁眼,都可以對(duì)其重寫。
class People(object):
country = 'china'
#類方法昭殉,用classmethod來(lái)進(jìn)行修飾
@classmethod
def getCountry(cls):
return cls.country
@classmethod
def setCountry(cls,country):
cls.country = country
p = People()
print (p.getCountry()) #可以用過(guò)實(shí)例對(duì)象引用
print (People.getCountry()) #可以通過(guò)類對(duì)象引用
p.setCountry('japan')
print (p.getCountry())
print (People.getCountry())
結(jié)果顯示在用類方法對(duì)類屬性修改之后苞七,通過(guò)類對(duì)象和實(shí)例對(duì)象訪問(wèn)都發(fā)生了改變
模塊
from part2.classdemo.car import Car
import會(huì)讓Python打開(kāi)模塊car并導(dǎo)入其中的Car類
?在一個(gè)模塊中存儲(chǔ)多個(gè)類
?從一個(gè)模塊導(dǎo)入多個(gè)類
可根據(jù)需要在程序文件中導(dǎo)入任意數(shù)量的類。從一個(gè)模塊中導(dǎo)入多個(gè)類時(shí)挪丢,用逗號(hào)分隔導(dǎo)入的個(gè)各類蹂风。導(dǎo)入必要的類后,就可以根據(jù)需要?jiǎng)?chuàng)建每個(gè)類的任意數(shù)量的實(shí)例
from part2.classdemo.car import Car, ElectricCar
模塊中的all
?被導(dǎo)入的模塊乾蓬,最上邊 加入 all = ['one' , 'two'] #添加的方法名稱對(duì)應(yīng)的方法惠啄。
在from test import * 導(dǎo)入的情況下, all 所指明的方法會(huì)被導(dǎo)入可以使用任内;其他的不會(huì)被*號(hào)導(dǎo)入撵渡;
?通過(guò)在文件開(kāi)頭
用 all 指定可以被 from……import* 導(dǎo)入的方法