參考:黑馬程序員教程 - Python基礎 面向對象html
OOP三大特性,且三個特性是有順序的:python
指的就是把現實世界的事務,封裝、抽象成編程裏的對象,包括各類屬性和方法。
這個通常都很簡單,不須要多講。程序員
惟一要注意的就是:推薦從小往大開始封裝、開發類。好比
手槍,子彈
這兩個類,咱們須要先定義和開發子彈的全部屬性和方法,而後再去開發上一層的手槍。這樣的話會很方便。反過來開發手槍的適合,發現寫到一半寫不下去要到子彈那裏寫,就很亂了。
子類能夠繼承父類和父父類的全部屬性、方法。編程
繼承格式:函數
class Parent: def func1(self): pass class Son(Parent): def func2(self): func1()
方法改寫:
子類在不滿意時,也能夠進行本身的改寫父類的屬性、方法。
其中有兩種狀況:ui
Extend 擴展父類函數:設計
super().func()
引用父類方法。其中super
是一個python builtin 特殊類,而super()
即生成一個super的實例。在子類中生成super實例,會獲得父類的引用。ParentName.func(self)
引用父類方法。可是不推薦,由於父類名稱改變的話全部的子類都要改。私有不繼承:
子類可以繼承的只是父類的公開內容,可是不包括父類的私有內容。
若是要訪問的話也能夠,可是須要間接的調用父類再用方法調用私有內容。code
Python中,子類是能夠同時有多個父類的:也就是可以同時繼承多個父類的全部屬性、方法。htm
繼承格式:對象
class Father: def func1(self): pass class Mother: def func2(self): pass class Son(Father, Mother): def func3(self): func1() func2()
注意:
若是多個父類間存在有同名的方法,那麼會繼承第一個父類的方法。
MRO, Method Resolution Order
查看繼承順序:
經過類自帶的.__mro__
屬性(MRO, Method Resolution Order
),能夠查看這個類的繼承順序。
子類能夠直接寫FatherName.func()
來調用父級函數。
可是當子類用super().func()
時候,python就會根據MRO
順序,由近到遠逐次尋找,找到最近的上級則返回。
用上例,若是是多繼承的話,那麼尋找順序是:SON -> Father -> Mother -> object
。
dir(className)
能夠查看內置全部屬性方法。
Python3開始使用新式的類定義,即默認讓全部定義的類都自動繼承一個叫object
的內置基礎類。object
基礎類定義了不少方便的屬性。包括18項之多。
而舊式的Python2.x時代,不繼承object基礎類,本身定義的類就只有__doc__
和__module__
兩樣內置屬性而已。2.x時代,若是須要手動繼承,如:
class MyClass(object): pass
多態是指,不一樣的子類對象調用相同的父類方法,會產生多態多樣結果的編程特性。
多態的前提是可以繼承父類的方法,且可以重寫改寫父類的方法。
多態的特色:
def Father(): def work(self): do_job() def do_job(self): print('Farming on the field...') def Son(Father): def do_job(self): print('Programming at an office...') # ---- Now let's work ---- Jason = Son() Jason.work()
以上代碼中,一樣是work()
函數,且要do_work()
。可是,不一樣的人調用的是不一樣的do_work
。
Father調用本身的do_work,兒子由於本身重寫了do_work,因此調用本身的方法。
這就是多態——所繼承的方法,不須要再特殊指定誰用什麼方法,而對象會自動調用適合本身的方法。
Python中,實例是一個對象,類也是一個對象,一切皆對象。但這也是Python OOP中引發不少麻煩的緣由。
實例對象很是好理解,也好用,直接用,就不說了。可是類對象
就不那麼好理解了。
簡單說,類對象
也是一個標準的對象,有本身的屬性和方法,只不過可以像模版
同樣生成多個實例對象而已。
類對象有這兩大研究點:
類屬性:就是能讓全部實例訪問和操做的公用廁所
類方法:比較難理解,必須用到名爲@classmethod
的裝飾器,函數的第一個參數必須是關鍵字cls
,如同self
。
@classmethod
裝飾器:用來告訴解釋器這是一個類方法
,而不是實例方法。cls
參數:這是Python OOP中困擾不少人的特色。可是其實不難理解,總結以下:
class MyClass: # 在這個位置定義的,叫類屬性。==等同於其它語言的「靜態屬性」 # 這是每一個實例共有的公用屬性,至關於宿舍的公用洗澡間 count = 0 def __init__(self): # 用self.定義的,叫實例屬性,是每一個實例只本身全部的屬性,selfish self.name = "Jason"
訪問類屬性的方法有兩種:
ClassName.propertyName
:推薦,直接用類名訪問類屬性。Instance.propertyName
:不推薦用實例名訪問類屬性,由於若是須要寫入操做,那麼這種方法只會給本身添加一個實例屬性,而不會影響類屬性。方法一:
>>> MyClass.newAttribute = 'I am a class attribute' >>> print( MyClass.newAttribute ) 'I am a class attribute'
方法二:裝飾器
# Customized decorator for classproperty class classproperty(object): def __init__(self, getter): self.getter= getter def __get__(self, instance, owner): return self.getter(owner) class MyClass: @classproperty def newAttribute(cls): return 'I am a class attribute.' >>> print( MyClass.newAttribute ) 'I am a class attribute'
之因此把方法封裝爲一個類屬性,是由於咱們有時候須要根據其它類屬性來定製這個類屬性。
而通常狀況下,咱們無法在類屬性定義的時候得到當前的類或類中其它的屬性。
類方法如同類屬性,是屬於全類的方法,可是(推薦)只用來訪問類屬性。
類方法:比較難理解,必須用到名爲@classmethod
的裝飾器,函數的第一個參數必須是關鍵字cls
,如同self
。
@classmethod
裝飾器:用來告訴解釋器這是一個類方法
,而不是實例方法。cls
參數:如同self
,用來指代當前的類。注意:@classmethod
和cls
都是關鍵字,不能改。
代碼:
class MyClass: # 定義一個「類屬性」 count = 0 # 這裏開始定義「類方法」 @classmethod def func(cls): print(cls.count)
類中的staticmethod
裝飾器一樣是python基礎類object的一個用於包裝、裝飾的方法。一旦在類方法前放上裝飾器@staticmethod
,方法就會轉換爲一個靜態方法
。
靜態方法就是一個很是獨立的方法:既不訪問實例的信息,也不訪問類的信息。
代碼:
class MyClass: # 定義一個「類屬性」 count = 0 # 這裏開始定義「類方法」 @staticmethod def func(): pass
類中的property
裝飾器,也是python基礎類object的一個用於包裝、裝飾的方法。一旦類方法前放上裝飾器@property
,方法就會轉換爲一個類屬性
。不少時候把方法假裝成屬性,是很是方便的。
class MyClass: # 這裏開始定義由方法轉換爲「類屬性」 @property def name(self): return "Jason" c = MyClass() print( c.name )
在繼承object基礎類的狀況下,python給出了三種類屬性裝飾,對應三種操做:
@property
@name.setter
@name.deleter
也就是說,當你讀取類屬性my_name
的時候,會調用被@property
修飾的方法;當你修改my_name
當時候,會調用被@my_name.setter
修飾的方法;當你刪除這個屬性時,會調用被@my_name.deleter
修飾的方法。
注意:
@property
, @*.setter
, @*.deleter
,這是固定的名字,不能改。代碼:
class MyClass: # 這裏開始定義由方法轉換爲「類屬性」 @property def name(self): return "Jason" @name.setter def name(self, value): self.name = value @name.deleter def name(self): del "Jason" c = MyClass() print( c.name ) # READ c.name = "Brown" # SET del c.name # DELETE
不少OOP語言,針對property屬性
,通常操做是:一個私有屬性,配合兩個公有方法。
如:
class MyClass: def __init__(self): self.__name = "Jason" def get_name(self): return self.__name def set_name(self, value): self.__name = value c = MyClass() # 開始調用 c.set_name("Brownee") print( c.get_name() )
在Python下,能夠利用裝飾器改成如下代碼,極大方便調用的過程:
class MyClass: def __init__(self): self.__name = "Jason" @property def name(self): return self.__name @name.setter def name(self, value): self.__name = value c = MyClass() # 開始調用 c.name = "Brownee" print( c.name )