Python——類(lèi)、面向?qū)ο?,封裝 繼承 多態(tài)
面向過(guò)程:根據(jù)業(yè)務(wù)邏輯從上到下寫(xiě)代碼
面向?qū)ο螅簩?shù)據(jù)與函數(shù)綁定到一起,進(jìn)行封裝,這樣能夠更快速的開(kāi)發(fā)程序,減少了重復(fù)代碼的重寫(xiě)過(guò)程
類(lèi)
人以類(lèi)聚 物以群分。
具有相似內(nèi)部狀態(tài)和運(yùn)動(dòng)規(guī)律的實(shí)體的集合(或統(tǒng)稱(chēng)為抽象)。
具有相同屬性和行為事物的統(tǒng)稱(chēng)
類(lèi)是抽象的,在使用的時(shí)候通常會(huì)找到這個(gè)類(lèi)的一個(gè)具體的存在,使用這個(gè)具體的存在。一個(gè)類(lèi)可以找到多個(gè)對(duì)象
在Python中編寫(xiě)類(lèi)的方式如下:
class Dog():
'''創(chuàng)建小狗的類(lèi)'''
def init(self,name,age):
self.name = name
self.age = age
'''動(dòng)作方法 play'''
def sit(self):
print('狗在玩')
方法init()
init()是一個(gè)特殊的方法,每當(dāng)根據(jù)類(lèi)創(chuàng)建類(lèi)的實(shí)例時(shí),Python都會(huì)自動(dòng)運(yùn)行這個(gè)方法。在這個(gè)方法中開(kāi)頭和末尾各有兩個(gè)下劃線。
避免Python默認(rèn)方法與普通方法發(fā)生名稱(chēng)沖突。
init()定義中我們傳遞了三個(gè)參數(shù):self、name和age。這個(gè)初始化方法中self是必須的。而且還必須位于其他的形參前面。每個(gè)與類(lèi)相關(guān)聯(lián)的方法調(diào)用都自動(dòng)傳遞實(shí)參self,它是一個(gè)指向?qū)嵗旧淼囊?。讓?shí)例能夠訪問(wèn)類(lèi)中的屬性和方法
在init()方法中定義的兩個(gè)變量都有前綴self。以self為前綴的變量都可供類(lèi)中的所有方法使用。
init()沒(méi)有并沒(méi)有顯式地包含return語(yǔ)句,但Python自動(dòng)返回類(lèi)對(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)建類(lèi)的方法
?在Python3.0中創(chuàng)建類(lèi)
class ClassName(Object):
pass
根據(jù)類(lèi)創(chuàng)建實(shí)例
my_dog = Dog()
my_dog.play()
為屬性指定默認(rèn)值
類(lèi)中的每個(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ē)產(chǎn)生了'
elif self.t>=8:
self.info='汽車(chē)各個(gè)部件噴涂'
elif self.t>=6:
self.info='汽車(chē)各個(gè)部件涂膠'
elif self.t>=5:
self.info='汽車(chē)各個(gè)部位點(diǎn)焊,弧焊,鉚焊'
else:
self.info='一堆鐵皮'
類(lèi)的繼承
在程序中,繼承描述的是事物之間的所屬關(guān)系,例如貓和狗都屬于動(dòng)物,程序中便可以描述為貓和狗繼承自動(dòng)物;同理,波斯貓和巴厘貓都繼承自貓,而沙皮狗和斑點(diǎn)狗都繼承足夠。
?定義子類(lèi)時(shí),必須在括號(hào)內(nèi)指定父類(lèi)的名稱(chēng)
?在創(chuàng)建子類(lèi)的實(shí)例時(shí),Python首先需要給父類(lèi)的所有屬性賦值。
?創(chuàng)建子類(lèi)時(shí),父類(lèi)必須包含在當(dāng)前文件中,且位于子類(lèi)前面。
?子類(lèi)中可以使用super()代表父類(lèi)的引用。
class Cat(object):
def init(self, name, color="白色"):
self.name = name
self.color = color
def run(self):
print("%s--在跑"%self.name)
定義一個(gè)子類(lèi),繼承Cat類(lèi)如下:
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()
類(lèi)——object
每一個(gè)python類(lèi)都隱含了一個(gè)超類(lèi):object,這個(gè)類(lèi)是一個(gè)非常簡(jiǎn)單的定義,這個(gè)類(lèi)幾乎不做任何事情。
重寫(xiě)、調(diào)用父類(lèi)方法
?所謂重寫(xiě),就是子類(lèi)中,有一個(gè)和父類(lèi)相同名字的方法,在子類(lèi)中的方法會(huì)覆蓋掉父類(lèi)中同名的方法
看幾個(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)用父類(lèi)的init方法1(python2)
#Cat.init(self,name)
# 調(diào)用父類(lèi)的init方法2
#super(Bosi,self).init(name)
# 調(diào)用父類(lèi)的init方法3
super().init(name)
def getName(self):
return self.name
bosi = Bosi('xiaohua')
print(bosi.name)
print(bosi.color)
多繼承
Python支持多繼承,我們知道子類(lèi)會(huì)繼承父類(lèi)中的屬性和方法。python中需要繼承多個(gè)類(lèi)的時(shí)候,使用如下的格式
class 子類(lèi)(父類(lèi)1,父類(lèi)2):
pass
那么當(dāng)多個(gè)父類(lèi)都含有相同的方法,會(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è)父類(lèi)中的相關(guān)方法
我們用圖解來(lái)解釋一下執(zhí)行順序
142800ycssa7s7m00aac2t.png
定義一個(gè)父類(lèi)
class A:
def printA(self):
print('----A----')
定義一個(gè)父類(lèi)
class B:
def printB(self):
print('----B----')
定義一個(gè)子類(lèi),繼承自A、B
class C(A,B):
def printC(self):
print('----C----')
obj_C = C()
obj_C.printA()
obj_C.printB()
python中是可以多繼承的
父類(lèi)中的方法、屬性,子類(lèi)會(huì)繼承
我們根據(jù)執(zhí)行結(jié)果,可以看到程序會(huì)現(xiàn)在子類(lèi)中查找要執(zhí)行的方法和函數(shù),然后會(huì)在第一個(gè)父類(lèi)中尋找如果沒(méi)有找到,會(huì)在第二個(gè)父類(lèi)中尋找。如果也沒(méi)有找到會(huì)去父類(lèi)的公共基類(lèi)找。
程序的執(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)方法和類(lèi)方法
是類(lèi)對(duì)象所擁有的方法,需要用修飾器@classmethod來(lái)標(biāo)識(shí)其為類(lèi)方法,對(duì)于類(lèi)方法,第一個(gè)參數(shù)必須是類(lèi)對(duì)象,一般以cls作為第一個(gè)參數(shù)(當(dāng)然可以用其他名稱(chēng)的變量作為其第一個(gè)參數(shù),但是大部分人都習(xí)慣以’cls’作為第一個(gè)參數(shù)的名字,就最好用’cls’了),能夠通過(guò)實(shí)例對(duì)象和類(lèi)對(duì)象去訪問(wèn)。
?靜態(tài)字段的創(chuàng)建
class People(object):
country = 'china'
@staticmethod
#靜態(tài)方法
def getCountry():
return People.country
print (People.getCountry())
類(lèi)方法
?調(diào)用get方法
test = duck('test123')
print(test.get_name)
?調(diào)用setter方法
test = duck('test123')
test.set_name = '123test'
print(test.get_name)
使用名稱(chēng)重整保護(hù)私有特性
在前面的Duck例子中,如果直接訪問(wèn)hidden_name還是可以看到對(duì)應(yīng)屬性的值。Python對(duì)那些需要可以隱藏在類(lèi)內(nèi)部的特性有自己的命名規(guī)范:由連續(xù)的兩個(gè)下劃線開(kāi)頭(__)
class People(object):
country = 'china'
#類(lèi)方法,用classmethod來(lái)進(jìn)行修飾
@classmethod
def getCountry(cls):
return cls.country
p = People()
print (p.getCountry()) #可以用過(guò)實(shí)例對(duì)象引用
print (People.getCountry()) #可以通過(guò)類(lèi)對(duì)象引用
類(lèi)方法還有一個(gè)用途就是可以對(duì)類(lèi)屬性進(jìn)行修改:
對(duì)于父類(lèi)的方法,只要它不符合子類(lèi)的調(diào)用行為,都可以對(duì)其重寫(xiě)。
class People(object):
country = 'china'
#類(lèi)方法,用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ò)類(lèi)對(duì)象引用
p.setCountry('japan')
print (p.getCountry())
print (People.getCountry())
結(jié)果顯示在用類(lèi)方法對(duì)類(lèi)屬性修改之后,通過(guò)類(lèi)對(duì)象和實(shí)例對(duì)象訪問(wèn)都發(fā)生了改變
模塊
from part2.classdemo.car import Car
import會(huì)讓Python打開(kāi)模塊car并導(dǎo)入其中的Car類(lèi)
?在一個(gè)模塊中存儲(chǔ)多個(gè)類(lèi)
?從一個(gè)模塊導(dǎo)入多個(gè)類(lèi)
可根據(jù)需要在程序文件中導(dǎo)入任意數(shù)量的類(lèi)。從一個(gè)模塊中導(dǎo)入多個(gè)類(lèi)時(shí),用逗號(hào)分隔導(dǎo)入的個(gè)各類(lèi)。導(dǎo)入必要的類(lèi)后,就可以根據(jù)需要?jiǎng)?chuàng)建每個(gè)類(lèi)的任意數(shù)量的實(shí)例
from part2.classdemo.car import Car, ElectricCar
模塊中的all
?被導(dǎo)入的模塊,最上邊 加入 all = ['one' , 'two'] #添加的方法名稱(chēng)對(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)入的方法