摘要:時代,如果需要手動繼承,如多態多態是指,不同的子類對象調用相同的父類方法,會產生多態多樣結果的編程特性。
參考:黑馬程序員教程 - Python基礎 面向對象
OOP三大特性,且三個特性是有順序的:
封裝
繼承
多態
封裝指的就是把現實世界的事務,封裝、抽象成編程里的對象,包括各種屬性和方法。
這個一般都很簡單,不需要多講。
唯一要注意的就是:推薦從小往大開始封裝、開發類。比如手槍,子彈這兩個類,我們需要先定義和開發子彈的所有屬性和方法,然后再去開發上一層的手槍。這樣的話會很方便。反過來開發手槍的適合,發現寫到一半寫不下去要到子彈那里寫,就很亂了。繼承
子類可以繼承父類和父父類的所有屬性、方法。
繼承格式:
class Parent: def func1(self): pass class Son(Parent): def func2(self): func1()
方法改寫:
子類在不滿意時,也可以進行自己的改寫父類的屬性、方法。
其中有兩種情況:
Overwrite 覆蓋重寫父類方法:只需要寫一個同名函數即可覆蓋。
Extend 擴展父類函數:
第一種方式(主要):寫一個同名函數,并在其中通過super().func()引用父類方法。其中super是一個python builtin 特殊類,而super()即生成一個super的實例。在子類中生成super實例,會得到父類的引用。
第二種方式(python 2.x以前使用):寫一個同名函數,再通過ParentName.func(self)引用父類方法。但是不推薦,因為父類名稱改變的話所有的子類都要改。
私有不繼承:
子類能夠繼承的只是父類的公開內容,但是不包括父類的私有內容。
如果要訪問的話也可以,但是需要間接的調用父類再用方法調用私有內容。
Python中,子類是可以同時有多個父類的:也就是能夠同時繼承多個父類的所有屬性、方法。
繼承格式:
class Father: def func1(self): pass class Mother: def func2(self): pass class Son(Father, Mother): def func3(self): func1() func2()
注意:
如果多個父類間存在有同名的方法,那么會繼承第一個父類的方法。
查看繼承順序:
通過類自帶的.__mro__屬性(MRO, Method Resolution Order),可以查看這個類的繼承順序。
子類可以直接寫FatherName.func()來調用父級函數。
但是當子類用super().func()時候,python就會根據MRO順序,由近到遠逐次尋找,找到最近的上級則返回。
用上例,如果是多繼承的話,那么尋找順序是:SON -> Father -> Mother -> object。
查看類的內置屬性和方法:dir(className)可以查看內置所有屬性方法。
Python內置的object基礎類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中引起很多麻煩的原因。
實例對象非常好理解,也好用,直接用,就不說了。但是類對象就不那么好理解了。
簡單說,類對象也是一個標準的對象,有自己的屬性和方法,只不過能夠像模版一樣生成多個實例對象而已。
類對象有這兩大研究點:
類屬性:就是能讓所有實例訪問和操作的公用廁所
定義類屬性:位于class的所有方法之外
訪問類屬性:className.propertyName
類方法:比較難理解,必須用到名為@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(): passProperty屬性
類中的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 # DELETEproperty屬性的應用
很多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 )
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/42979.html
摘要:面向對象編程之旅編程是什么大家好,作為小白,最近學習了很多編程的知識,因為腦容量有限,特此一一按照學習順序記錄下來,如果哪里有錯誤,還請大神盡快指出,以免誤導他人。。。繼承也允許把一個派生類的對象作為一個基類對象對待。 Python面向對象編程之旅 OOP編程是什么 大家好,作為小白,最近學習了很多Python OOP編程的知識,因為腦容量有限,特此一一按照學習順序記錄下來,如果哪里有...
摘要:類的方法概覽首先回顧一下常見的三種方法實例接口方法類方法靜態方法標準書寫方式如下我們最常用的其實就是普通的接口方法,其他兩個需要用類似裝飾器的寫法來標注。類方法接受一個作為參數,它是指向本身的,并不是所創建的實例。 類的方法概覽 首先回顧一下Python OOP常見的三種方法: instance method 實例/接口方法 class method 類方法 static...
摘要:學習廖雪峰官方網站教程總結面向對象編程總結,供日后參考類和實例類的定義限制實例只能添加指定的屬性類屬性初始化值,創建實例必須綁定的屬性變量設置,保證類內部數據安全創建類,實質上是元類,類的定義本質上就是利用創建類先定義函數創建實例報錯,不能 學習廖雪峰官方網站python教程總結python面向對象編程OOP(Object Oriented Programming)總結,供日后參考1....
摘要:反對者在某些領域對此予以否認。下面再引用一段來自維基百科中關于的歷史。類的更嚴格的定義是由某種特定的元數據所組成的內聚的包。類還可以有運行時表示形式元對象,它為操作與類相關的元數據提供了運行時支持。 在開始部分,請看官非常非常耐心地閱讀下面幾個枯燥的術語解釋,本來這不符合本教程的風格,但是,請看官諒解,因為列位將來一定要閱讀枯燥的東西的。這些枯燥的屬于解釋,均來自維基百科。 1、問題...
閱讀 1669·2021-11-19 09:40
閱讀 2924·2021-09-24 10:27
閱讀 3215·2021-09-02 15:15
閱讀 1876·2019-08-30 15:54
閱讀 1202·2019-08-30 15:54
閱讀 1369·2019-08-30 13:12
閱讀 626·2019-08-28 18:05
閱讀 2794·2019-08-27 10:53