面向對象介紹

1.什么是面向對象和面向過程編程思想

面向過程:

專注于為中小企業提供做網站、成都做網站服務,電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業東陽免費做網站提供優質的服務。我們立足成都,凝聚了一批互聯網行業人才,有力地推動了千余家企業的穩健成長,幫助中小企業通過網站建設實現規模擴充和轉變。

1.核心是‘過程’二字
2.過程的含義是將程序流程化
3.過程是流水線,用來分步驟解決問題的

程序=數據+功能

面向對象:

1.核心是‘對象’二字
2.對象的含義是將程序進行整合
3.對象是‘容器’,用來盛放數據和功能(變量和函數)

總結:以做西紅柿雞蛋面為例:

面向過程:我需要買西紅柿--》買雞蛋、面--》把西紅柿洗好、雞蛋打好...等等
面向對象:找個人幫我干活,我只需要告訴那個人我需要吃西紅柿雞蛋面(調用該對象),具體的過程交給別人干。

python中可以用來盛放數據和功能的‘容器’可以是字典、列表、集合等。但是這些容器在存放功能的時候,并不能把功能的具體代碼全部傳進去(只能傳一個函數名),這就有一定的局限性!

那么。python中提供了什么樣的語法來讓我們更好的存放數據和功能呢??

2.類

類,其實也是‘容器’,它是用來存放對象1、對象2、對象3...等共有的數據和功能!

它能夠更好的節省空間并且幫我們更好完成面向對象的編程!

2.1 類的引入

先定義類(找到對象共有的數據和功能),然后在調用類產生具體的對象!!

# 所有類體中最常見的就是變量和功能的定義,但是類體中也可以包含其他代碼
# 注意:類體中的代碼是在定義階段就會執行的,也就是說在定義階段就開辟了名稱空間

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)

2.2 類的調用--產生對象

# 類的調用,類名()的方式返回了一個class_obj對象,就是把類和該對象建立了一個聯系,該對象就可以使用類里面的定義的變量和功能了
class_obj = ClassName()

# 該對象的.__dict__方法得到的是一個空字典,可以使用對象.屬性名=屬性值的方式給該字典添加值
print(class_obj.__dict__)

# 類名.變量名/類名.函數名 調用類的變量和功能
print(class_obj.var)

2.3 類的__init__方法

當對象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

2.4 類中的屬性查找和綁定方法

1.數據屬性的查找

類中屬性查找的順序是對象先從自己那查找,如果找不到該屬性,則去類里面查找。對象修改添加屬性和屬性值,這并不會影響類里面對應的屬性,其余對象獲取到的還是原來類里面定義的屬性值

類中定義了對象所需要的所有的共有屬性和功能,大家訪問共有屬性和功能的地址都是一樣的。

2.類中函數方法的綁定

正在調用類中的方法是需要按照:類名.函數名(對象)的方法進行調用,但是這樣未免太過麻煩。

所以,類提供了一種綁定方法:對象在調用類中功能(函數)時,會自動把該對象當成參數自動傳入。
對象1.類中函數名()==類名.函數名(對象) #這里默認函數名傳入了對象1

回顧一下列表、字典,其實也是采用了類的思想!
l=[11,22,33] 等價于 l=list([11,22,33])
其實list就是一個類,l就是一個對象
l.append('dd')等價于list.append(l,'dd') 就是調用list類里的append方法

2.5 類中如何隱藏屬性和方法

在屬性名和方法前加__前綴,就會實現一個隱藏的效果,外界就不能調用該屬性了。

該方法和屬性只是語法形式上的變形,通過__dict__查看其真正的語法名,然后在外部也是可以訪問到的!

隱藏屬性和方法在外部訪問不到,但是在類內部還是可以訪問到的

這樣操作的目的是:不讓外部輕易的訪問到內部的屬性,即使需要訪問,也必須需要一些條件。比如:需要訪問類中的隱藏屬性就必須調用類中的某種方法(方法中可以進行判斷、條件限制),符合條件則該方法里可以訪問到隱藏屬性!!

2.6 類中的property

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 #修改名字

2.7 類中classmethod方法

在類中,我們定義的方法默認是綁定給對象的,即在實例化類的時候,對象會默認當成參數傳入到類中的方法里面。
obj = ClassName() #這里obj自動傳入了

如何定義一個方法,該方法是默認傳入類的呢??

只需要在我們需要綁定的方法前面加上@classmethod就行,下次我們在調用該類的方法時會自動傳入該類名,調用者是類。

class B:
    @classmethod
    def fun(cls):
        return cls(xxx,xxx) 
# 調用類方法
B.fun()  # 會自動將類自動穿給cls,然后調用fun函數,提供了一種新的造對象的方式

用途:提供了一種新的造對象的方式

2.8 類中的staticmethod方法

不需要綁定給類或者對象的方法,在對應函數上加上@staticmethod,調用者可以是類或者對象,沒有自動傳參的效果。

class B:
    @staticmethod
    def fun(v,y):
        pass
		
obj = 	B()
# 靜態方法可以通過類或者對象調用
obj.fun(v,y)
B.fun(v,y)

3. 面向對象的三大特性

3.1 封裝

封裝其實就是整合,對于共有的數據和功能進行整合。

3.2 繼承

3.2.1 什么是繼承

繼承是一種創建新類的方式,新建的類可以稱為子類或者派生類,繼承的類可以稱為父類或者基類

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__) #查看對應類的父類

3.2.2 為什么要用繼承

優點:類是用來對象數據和功能冗余的問題,而類是用來解決類與類的冗余
缺點:代碼的可讀性變差,擴展性也將變差(現實中不建議使用多繼承,如果要用,建議使用Mixins機制)

3.2.3 繼承中的菱形問題的屬性查找(后磚石問題)

菱形問題實際指的是,在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線性化算法來實現的(了解一下即可)。

3.2.4 非菱形問題下的查找順序

python2和3的查找順序為:A-->B--->E--->C--->F--->D---object(按照圖中從左到右的分支一個個查找)

3.2.5 多繼承下的mixins機制

mixins機制的核心:就是在多繼承的背景下盡可能的提升多繼承的可讀性

python的多繼承類中,應當只有一個標識其歸屬含義的父類,意思是保證多繼承的類遵循繼承‘is-a’的原則,其余繼承的類都應該是mixin類,該類的命名規范一般是以mixin、able、ible為后綴。

mixin類只是用來表達某一類功能的類,并不決定子類的歸屬,它也不依賴于子類的實現,而且子類也并不是完全依賴mixin類,缺少了該類,子類照常工作,只是缺少了某種功能罷了!!

最后,mixin類盡量少用,當mixin類很多的時候,依然會造成可讀性差的問題!!

3.2.6 子類派生的新方法中如何重用父類功能

法一:指名道姓的調用某一個類下面的函數,該方法不依賴類的繼承


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())

3.3 多態與鴨子類型

3.3.1什么是多態

多態指的是:同一種事物有多種形態

多態性和鴨子類型的本質在于,不同的類中定義了相同的方法名,這樣我們就可以不考慮類而統一用一種方式去使用對象。

比如,所有的類中都定義了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。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

成都定制網站建設
主站蜘蛛池模板: 国产真人无码作爱免费视频| 亚洲无码高清在线观看 | 人妻少妇偷人精品无码 | 久久水蜜桃亚洲av无码精品麻豆 | 亚洲AV成人噜噜无码网站| av无码免费一区二区三区| 精品久久久久久无码中文字幕| 亚洲第一极品精品无码久久| 国产精品无码一区二区三区不卡| 亚洲熟妇无码AV在线播放| 亚洲AV无码一区二区三区网址| 中文午夜乱理片无码| 东京热一精品无码AV| 亚洲日韩乱码中文无码蜜桃| 国产AⅤ无码专区亚洲AV| 欧美性生交xxxxx无码影院∵| 人妻少妇偷人精品无码| 亚洲精品无码永久中文字幕| 日韩精品无码免费视频| 日韩成人无码一区二区三区| 日韩av无码一区二区三区| 国产成人无码av| 精品无码久久久久久久久久| 大胆日本无码裸体日本动漫 | 久久精品无码一区二区无码| 亚洲日韩av无码| 亚洲一级特黄无码片| 国产精品亚洲а∨无码播放麻豆| 亚洲中文无码永久免| 在线观看成人无码中文av天堂| 久久无码高潮喷水| 亚洲精品无码久久毛片波多野吉衣| 亚洲日韩中文无码久久| 亚洲中文字幕无码爆乳AV| 亚洲午夜无码久久久久| 国产白丝无码免费视频| 亚洲Av无码专区国产乱码DVD| 亚洲AV中文无码字幕色三| 亚洲国产精品无码久久久蜜芽| 国产成人精品无码免费看| 无码人妻精品一区二区三区夜夜嗨|