一、OOP
oop就是代碼的重用,通過分解代碼,最小化代碼的冗餘以及對現存的代碼進行定製來編寫程序;OOP模型中有兩種對象,類對象和實例對象。類對象提供默認行爲,是生產實例對象的工廠;類對象和實例對象都有各自命名空間。
二、python類的主要特性
• class語句創建類對象並將其賦值給變量名
• class語句內的頂層賦值語句會創建類的屬性
• 類屬性提供對象的狀態和行爲
三、python實例對象的主要特性
• 每次類調用時,都會創建並返回新的實例對象
• 每個實例對象繼承類的屬性並獲得了自己的命名空間
• 每個實例對象通過構造方法獲得每個實例自己的屬性
四、創建類和實例對象-類的封裝
封裝,是將對象的數據與操作數據的方法相結合,通過方法將對象的數據與實現細節保護起來,就稱爲封裝。外界只能通過對象的方法訪問對象,因此封裝同時也實現了對象的數據隱藏
class Person():
#類的屬性--靜態屬性
country="China"
#封裝--初始化方法
def __init__(self,*args):
self.name=args[0]
self.age=args[1]
self.aggr=args[2]
self.sex=args[3]
#方法
def walk(self,n):
print("%szoule%sbu"%(self.name,n))
#調用類創建實例對象,自動執行構造方法__init__
jonny=Person('jonny',11,23,'man')
#實例對象調用類的方法
jonny.walk(10)
#實例對象調用類的屬性
print(jonny.country)
五、類的繼承
單繼承
類可以通過繼承進行定製;類的繼承豐富了軟件的層級,在層級較低的地方覆蓋現有的屬性,讓其行爲特定化。
在python中,實例對象從類中繼承,而類繼承於超類
• 超類寫在類開頭的括號中
• 類從其超類中繼承屬性
• 實例會繼承所有可讀取類的屬性
• 每次實例對象的屬性調用都會進行類樹搜索
• 邏輯的修改是通過創建子類,而不是修改超類
#創建父類---經典類
class a():
a1="11"
#創建子類,繼承父類a
class b(a):
b1="22"
#調用父類的屬性
print(b.a1)
以上的例子中父類是經典類,因爲父類未繼承object類;繼承object類的父類是新式類
在python3之後,所有類默認繼承object類,就是說所有類都是新式類。
#創建父類---新式類
class a(object):
a1="11"
#創建子類,繼承父類a
class b(a):
b1="22"
#調用父類的屬性
print(b.a1)
在繼承中,父類是經典類那麼子類就是經典類;父類是新式類,子類就是新式類,Python3之後,所有類都是新式類
多繼承
python支持繼承多個類,那麼在繼承父類的屬性和方法時改怎麼找呢?
class D(object):
def display(self):
print('D.display')
class C(D):
def display(self):
print('C.display')
class B(D):
def display(self):
print('B.display')
class A(B,C):
def display(self):
print('A.display')
a=A()
a.display()
多繼承中,子類的對象調用一個方法,默認是就近原則,在python2.7之前的經典類中是深度優先,在python3之後的新式類中是廣度優先。
執行display方法時,查找順序爲 A--B--C--D
Python3中繼承特性的新方法
mro()
類的函數mro()記錄了繼承的順序,mro()
A.mro()
結果如下:
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>]
super()
super方法是python3之後版本纔有的,用於新式類,super方法是根據調用者的節點位置的廣度優先順序來調用父類的函數或方法的。
兩種調用方式
1、父類名.方法名,需要自己傳self參數
2、super().方法名,不需要自己傳self
class Person(object):
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def eat(self):
print("eatfood")
class Teacher(Person):
def __init__(self,name,age,sex,school,cls):
Person.__init__(self,name,age,sex)
#派生方法
def score(self):
print("teacherscore")
def eat(self):
print("teachereating")
t1=Teacher("adc",42,"man","127","python1ban")
print(t1.name)
#傳入類和對象,調用父類的方法
super(Teacher,t1).eat()
六、類的多態
類的多態性是指具有不同功能的函數可以使用相同的函數名,這樣就可以用一個函數名調用不同內容的函數。
class Person():
def display(self):
pass
class Man(Person):
def display(self):
print("man")
class Woman(Person):
def display(self):
print("woman")
def func(obj):
obj.display()
#實例化對象
man1=Man()
woman1=Woman()
#多態
func(man1)
func(woman1)
七、組合
一個對象的屬性值是另外一個類的對象
class Birthday():
def __init__(self,year,month,day):
self.year=year
self.month=month
self.day=day
class Person():
def __init__(self,name,age,birthday):
self.name=name
self.age=age
self.birthday=birthday
bd=Birthday(2019,11,11)
jonny=Person("jonny",20,bd)
#組合調用
print(jonny.birthday.year)
八、派生
父類中沒有的屬性,在子類中出現,叫做派生屬性
父類中沒有的方法,在子類中出現,叫做派生方法
class Person(object):
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def eat(self):
print("eatfood")
class Teacher(Person):
def __init__(self,name,age,sex,school,cls):
Person.__init__(self,name,age,sex)
#派生方法
def score(self):
print("teacherscore")
def eat(self):
print("teachereating")
t1=Teacher("adc",42,"man","127","python1ban")
print(t1.name)
#傳入類和對象,調用父類的方法
super(Teacher,t1).eat()
九、面向對象的編程規範:接口類與抽象類
接口類與抽象類的不同點:
接口類:支持多繼承,接口類中的所有的方法都必須不能實現;python中沒有接口類,java沒有多繼承,所以爲了接口隔離原則,設計了接口這個概念
抽象類:不支持多繼承,抽象類中的方法可以有一些代碼的實現;python自帶多繼承,所以直接用class來實現接口類;python支持抽象類,一般情況下單繼承,java本來就有單繼承,所以就有了抽象類。
接口類與抽象類的相同點:
1、都依賴abc模塊實現
2、都是面向對象的編程規範
3、接口類和抽象類都不能實例化
一般情況下,單繼承,能實現的功能是一樣的,所以在父類中可以有簡單的基礎實現
多繼承的情況下,由於功能比較複雜,所以不容易抽象出相同的功能的具體實現寫在父類中
接口類的實現:
from abc import abstractmethod,ABCMeta
class Payment(metaclass=ABCMeta):#元類,默認的元類type
@abstractmethod
def pay(self,money):pass
#raiseNotImplemented#手動拋異常,沒有實現這個方法
#規範:接口類或者抽象類都可以
#接口類:支持多繼承,接口類中的所有的方法都必須不能實現-----java
#抽象類:不支持多繼承,抽象類中的方法可以有一些代碼的實現-----java
class Wechatpay():
defpay(self,money):
print("微信支付了%s元"%money)
class Alipay():
defpay(self,money):
print("ali支付了%s元"%money)
def pay(pay_obj,money):#統一支付接口
pay_obj.pay(money)
wechat=Wechatpay()
ali=Alipay()
pay(ali,200)
接口類多繼承示例:
from abc import ABCMeta,abstractmethod
class Swim_Animal(metaclass=ABCMeta):
@abstractmethod
def swim(self):
pass
class Walk_Animal(metaclass=ABCMeta):
@abstractmethod
def walk(self):pass
class Fly_Animal(metaclass=ABCMeta):
@abstractmethod
def fly(self):pass
class Tiger(Walk_Animal,Swim_Animal):
def swim(self):pass
def walk(self):pass
class Swan(Walk_Animal,Swim_Animal,Fly_Animal):
def swim(self):pass
def walk(self):pass
def fly(self):pass
class Oldying(Walk_Animal,Fly_Animal):
def walk(self):pass
def fly(self):pass
抽象類示例:
from abc import abstractmethod,ABCMeta
class All_file(metaclass=ABCMeta):
@abstractmethod
def read(self):#規範子類必須有的方法
print("du")
@abstractmethod
def write(self):
print("xie")
class Doc(All_file):
def read(self):pass
def write(self):pass
classTxt(All_file):
def read(self):pass
def write(self):pass
class Ppt(All_file):
def read(self):print("pptdu")
def write(self):pass
p1=Ppt()
p1.read()