面向過程:
專注于為中小企業提供做網站、成都做網站服務,電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業東陽免費做網站提供優質的服務。我們立足成都,凝聚了一批互聯網行業人才,有力地推動了千余家企業的穩健成長,幫助中小企業通過網站建設實現規模擴充和轉變。
1.核心是‘過程’二字
2.過程的含義是將程序流程化
3.過程是流水線,用來分步驟解決問題的
程序=數據+功能
面向對象:
1.核心是‘對象’二字
2.對象的含義是將程序進行整合
3.對象是‘容器’,用來盛放數據和功能(變量和函數)
總結:以做西紅柿雞蛋面為例:
面向過程:我需要買西紅柿--》買雞蛋、面--》把西紅柿洗好、雞蛋打好...等等
面向對象:找個人幫我干活,我只需要告訴那個人我需要吃西紅柿雞蛋面(調用該對象),具體的過程交給別人干。
python中可以用來盛放數據和功能的‘容器’可以是字典、列表、集合等。但是這些容器在存放功能的時候,并不能把功能的具體代碼全部傳進去(只能傳一個函數名),這就有一定的局限性!
那么。python中提供了什么樣的語法來讓我們更好的存放數據和功能呢??
類,其實也是‘容器’,它是用來存放對象1、對象2、對象3...等共有的數據和功能!!
它能夠更好的節省空間并且幫我們更好完成面向對象的編程!
先定義類(找到對象共有的數據和功能),然后在調用類產生具體的對象!!
# 所有類體中最常見的就是變量和功能的定義,但是類體中也可以包含其他代碼
# 注意:類體中的代碼是在定義階段就會執行的,也就是說在定義階段就開辟了名稱空間
class ClassName: # 類的定義 class 類名(駝峰體命名規則):
# 變量(數據)的定義
var = 111
# 功能的定義
def send(self):
pass
def rcv(self):
pass
# 類中提供了一個方法查看類的名稱空間.__dict__,得到一個字典
print(ClassName.__dict__)
# __dict__[key]調用類體中的變量值或者功能
print(ClassName.__dict__['send'])
# 為了簡便上述的調用方式,類提供了.變量/.函數名的方法來調用,注意不加括號
print(ClassName.send)
# 類的調用,類名()的方式返回了一個class_obj對象,就是把類和該對象建立了一個聯系,該對象就可以使用類里面的定義的變量和功能了
class_obj = ClassName()
# 該對象的.__dict__方法得到的是一個空字典,可以使用對象.屬性名=屬性值的方式給該字典添加值
print(class_obj.__dict__)
# 類名.變量名/類名.函數名 調用類的變量和功能
print(class_obj.var)
當對象1、對象2、對象3...等的屬性都一樣,只是值不同的時候,我們不斷的使用對象.屬性=屬性值給對象賦值的時候,不免需要個每個對象都這樣操作,這樣會使得代碼冗余。
因此類中有一個 __init__的初始化方法,會自動幫你封裝好這個對象獨有的屬性,你只需要在調用的時候傳入對應的屬性值就行。
class ClassName:
# 參數self表示調用類時產生的對象,x和y是調用類時對應傳入的參數
def __init__(self,x,y):
self.name = x
self.age = y
# 調用類產生對象的操作,實際上是類的實例化的過程,這個過程發生了三件事
# 1.產生了一個空對象
# 2.自動調用類里面的__init__方法,并將調用時候的參數對應傳給__init__方法
# 3.返回初始化好的對象class_obj
class_obj = ClassName('zhang',18)
總結:
1.該方法會在調用類的時候自動執行,用來為對象初始化自己獨有的屬性
2.該方法內存放的是為對象初始化屬性的功能,但是也可以存放其他需要在調用時就執行的代碼
3.該方法的返回值只能是none
1.數據屬性的查找
類中屬性查找的順序是對象先從自己那查找,如果找不到該屬性,則去類里面查找。對象修改添加屬性和屬性值,這并不會影響類里面對應的屬性,其余對象獲取到的還是原來類里面定義的屬性值
類中定義了對象所需要的所有的共有屬性和功能,大家訪問共有屬性和功能的地址都是一樣的。
2.類中函數方法的綁定
正在調用類中的方法是需要按照:類名.函數名(對象)的方法進行調用,但是這樣未免太過麻煩。
所以,類提供了一種綁定方法:對象在調用類中功能(函數)時,會自動把該對象當成參數自動傳入。
對象1.類中函數名()==類名.函數名(對象) #這里默認函數名傳入了對象1
回顧一下列表、字典,其實也是采用了類的思想!
l=[11,22,33] 等價于 l=list([11,22,33])
其實list就是一個類,l就是一個對象
l.append('dd')等價于list.append(l,'dd') 就是調用list類里的append方法
在屬性名和方法前加__前綴,就會實現一個隱藏的效果,外界就不能調用該屬性了。
該方法和屬性只是語法形式上的變形,通過__dict__查看其真正的語法名,然后在外部也是可以訪問到的!
隱藏屬性和方法在外部訪問不到,但是在類內部還是可以訪問到的
這樣操作的目的是:不讓外部輕易的訪問到內部的屬性,即使需要訪問,也必須需要一些條件。比如:需要訪問類中的隱藏屬性就必須調用類中的某種方法(方法中可以進行判斷、條件限制),符合條件則該方法里可以訪問到隱藏屬性!!
property其實就是一種裝飾器,它的功能是把類中的方法偽裝成數據屬性,調用的時候就不用調用該方法了,直接把方法當成數據調用即可(不用加括號了)。
class ClassName:
def __init__(self):
self.__name = name
@property #法一:
def get(self):
return __self.name
def set(self,val):
self.__name = val
# 法二:偽裝的更像了
name = property(get,set)
# 法二改進:直接在函數上加@name.setter(修改值裝飾器)@name.deleter(刪除值裝飾器)@property(獲取值裝飾器),然后把函數名都改成name
class_obj = ClassName()
# 法一調用,不用加括號了
class_obj.get
# 法二調用
class_obj.name #獲取名字
class_obj.name=123 #修改名字
在類中,我們定義的方法默認是綁定給對象的,即在實例化類的時候,對象會默認當成參數傳入到類中的方法里面。
obj = ClassName() #這里obj自動傳入了
如何定義一個方法,該方法是默認傳入類的呢??
只需要在我們需要綁定的方法前面加上@classmethod就行,下次我們在調用該類的方法時會自動傳入該類名,調用者是類。
class B:
@classmethod
def fun(cls):
return cls(xxx,xxx)
# 調用類方法
B.fun() # 會自動將類自動穿給cls,然后調用fun函數,提供了一種新的造對象的方式
用途:提供了一種新的造對象的方式
不需要綁定給類或者對象的方法,在對應函數上加上@staticmethod,調用者可以是類或者對象,沒有自動傳參的效果。
class B:
@staticmethod
def fun(v,y):
pass
obj = B()
# 靜態方法可以通過類或者對象調用
obj.fun(v,y)
B.fun(v,y)
封裝其實就是整合,對于共有的數據和功能進行整合。
繼承是一種創建新類的方式,新建的類可以稱為子類或者派生類,繼承的類可以稱為父類或者基類
python支持多繼承,就是一個新建的類可以繼承多個父類,python3默認繼承object類,在python2中繼承了object的叫新式類,沒有繼承的叫經典類,python2中需要手動書寫需要繼承的類,不會默認繼承object。
class Student(object):
pass
class Student2(object):
pass
class Sub(Student):# 父類是Student
pass
class Sub2(Student,Student2): # 父類是Student和Student2
pass
print(Sub2.__bases__) #查看對應類的父類
優點:類是用來對象數據和功能冗余的問題,而類是用來解決類與類的冗余
缺點:代碼的可讀性變差,擴展性也將變差(現實中不建議使用多繼承,如果要用,建議使用Mixins機制)
菱形問題實際指的是,在python2和python3中菱形模式的繼承會導致,繼承查找順序不一致的問題!!,這個需要注意!
注意:菱形繼承最終繼承的A類是一個非object類,才叫菱形繼承
D類繼承了B和C類,B和C類分別繼承了A類,如果A中有一個方法,B和C都重寫了該方法,而D沒有重寫,那么D繼承的是哪個版本的方法呢?
class A:
def test(self):
print('from A')
class B(A):
def test(self):
print('from B')
class C(A):
def test(self):
print('from C')
class D(B,C):
pass
print(D.mro()) #該方法可以得到一個mro列表,列表里就是該類屬性查找的順序列表!
obj = D()
obj.test()
# 查找會從D-->B-->C-->A-->object,如果D的父類順序換了,則查找順序也會變成D-->C-->B-->A-->object(廣度優先原則),python2中的經典類就不一樣了,查找順序為D-->B-->A-->C深度優先原則)
其實,對于你定義的每一個類,python都會計算出一個方法解析順序(MRO)列表,該MRO列表就是一個簡單的所有基類的線性順序列表。
對象.mro()或者類.mro() #查看MRO線性順序列表
python會在MRO列表中從左到右開始查找基類,知道找到第一個匹配這個屬性的類為止,這個MRO列表的構造是通過一個C3線性化算法來實現的(了解一下即可)。
python2和3的查找順序為:A-->B--->E--->C--->F--->D---object(按照圖中從左到右的分支一個個查找)
mixins機制的核心:就是在多繼承的背景下盡可能的提升多繼承的可讀性
python的多繼承類中,應當只有一個標識其歸屬含義的父類,意思是保證多繼承的類遵循繼承‘is-a’的原則,其余繼承的類都應該是mixin類,該類的命名規范一般是以mixin、able、ible為后綴。
mixin類只是用來表達某一類功能的類,并不決定子類的歸屬,它也不依賴于子類的實現,而且子類也并不是完全依賴mixin類,缺少了該類,子類照常工作,只是缺少了某種功能罷了!!
最后,mixin類盡量少用,當mixin類很多的時候,依然會造成可讀性差的問題!!
法一:指名道姓的調用某一個類下面的函數,該方法不依賴類的繼承
class A:
def __init__(self,name,age):
self.name = name
self.age = age
class B:
def __init__(self,name,age,work):
A.__init__(self,name,age) # 法一:指名道姓
self.work = work
obj = B('zhang','18','python')
print(obj.__dict__)
法二:super()方法,該方法嚴格依賴繼承關系
調用super()會得到一個特殊的對象,注意該對象是參照當前發起屬性查找那個類的mro,去當前類的父類中查找屬性!! 輔助下面的列子進行理解!
class A:
def test(self):
print('from A')
super(A, self).test() # python3中super也可以省略括號里的參數
class B:
def test(self):
print('from B')
class C(A,B):
pass
obj = C()
obj.test()
# 1.首先會到obj對象里面去找test方法
# 2.再去C里面找
# 3.再去A里面找test方法,找到了打印
# 4.然后遇到了super()會得到一個特殊的對象,該對象參照當前發起屬性查找的類的mro就是C這個類,去當前調用super()方法的父類中查找test屬性
# 5.C這個類的mro是[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
# 6.當前super()方法的父類是B
print(C.mro())
多態指的是:同一種事物有多種形態
多態性和鴨子類型的本質在于,不同的類中定義了相同的方法名,這樣我們就可以不考慮類而統一用一種方式去使用對象。
比如,所有的類中都定義了read和write方法,那么我們在調用的時候就可以不考慮類,直接讓類實例化出來的對象調用read和write方法就行。
class Animal:
def say():
pass
def run():
pass
class People:
def say():
pass
def run():
pass
class Dog:
def say():
pass
def run():
pass
obj1=Animal()
obj2=People()
obj3=Dog()
我們在使用的時候就可以任何對象都可以.say、.run,而不用考慮類名
同時,我們也可以開設一個統一的接口,該接口只需要傳入對象就可以自動調用對象對應的方法了
def say(obj):
obj.say()
在python中,我們可以用父類規范子類(在父類中的方法,子類必須有)
import abc
# 使父類繼承一個抽象基類
class Person(metaclass=abc.ABCMeta):
# 在需要子類必須擁有該方法的上面加上@abc.abstractmethod
@abc.abstractmethod
def say(self):
print('xixixi')
class A(Person):
# 子類沒有該方法會報錯
def say(self):
pass
obj = A()
分享文章:面向對象介紹
當前鏈接:http://m.kartarina.com/article12/dsogidc.html
成都網站建設公司_創新互聯,為您提供Google、微信小程序、定制網站、標簽優化、營銷型網站建設、網站設計公司
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯