中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python面向對象類如何編寫

發布時間:2021-08-07 13:51:13 來源:億速云 閱讀:130 作者:小新 欄目:開發技術

這篇文章給大家分享的是有關Python面向對象類如何編寫的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

類代碼編寫細節

繼續學習類、方法和繼承。

class語句

以下是class語句的一般形式:

class <name>(superclass,...):
  data = value
  def method(self,...):
    self.member = value

在class語句內,任何賦值語句都會產生類屬性,而且還有特殊名稱方法重載運算符。例如,名為__init__的函數會在實例對象構造時調用(如果定義過的話)。

例子

類是命名空間,也就是定義變量名(屬性)的工具。

1.就像函數一樣,class語句是本地作用域,由內嵌的賦值語句建立的變量名,就存在于這個本地作用域內。

2.就像模塊內的變量名,在class語句內賦值的變量名會變成類對象中的屬性。

因為class是復合語句,所以任何種類的語句都可位于其主體內:print、=、if、def等。當class語句自身執行時,class語句內的所有語句都會執行。在class語句內賦值的變量名,會創建類屬性,而內嵌的def則會創建類方法。

例如,把簡單的非函數的對象賦值給類屬性,就會產生數據屬性,由所有實例共享。

>>> class ShareData:
  spam = 42
>>> x = ShareData()
>>> y = ShareData()
>>> x.spam,y.spam
(42, 42)

在這里,因為變量名spam是在class語句的頂層進行賦值的,因此會附加在這個類中,從而為所有的實例共享。我們可通過類名稱修改它,或者是通過實例或類引用它。

>>> ShareData.spam = 99
>>> x.spam,y.spam,ShareData.spam
(99, 99, 99)

這種類屬性可以用于管理貫穿所有實例的信息。例如,所產生的實例的數目的計數器。

現在,如果通過實例而不是類來給變量名spam賦值時,看看會發生什么:

>>> x.spam = 88
>>> x.spam,y.spam,ShareData.spam
(88, 99, 99)

對實例的屬性進行賦值運算會在該實例內創建或修改變量名,而不是在共享的類中。

對對象屬性進行賦值總是會修改該對象,除此之外沒有其他的影響。例如,y.spam會通過繼承而在類中查找,但是,對x.spam進行賦值運算則會把該變量名附加在x本身上。

看下面這個例子,可以更容易理解這種行為,把相同的變量名儲存在兩個位置:

>>> class MixedNames:
  data = 'spam'
  def __init__(self,value):
    self.data = value
  def display(self):
    print(self.data,MixedNames.data)

當創建這個類的實例的時候,變量名data會在構造函數方法內對self.data進行賦值運算,從而把data附加到這些實例上。

>>> x = MixedNames(1)
>>> y = MixedNames(2)
>>> x.display(),y.display()
1 spam
2 spam
(None, None)

【這里的(None,None)是調用display函數的返回值】

結果就是,data存在于兩個地方:在實例對象內(由__init__中的self.data賦值運算所創建)以及在實例繼承變量名的類中(由類中的data賦值運算所創建)。類的display方法打印了這兩個版本,先以點號運算得到self實例的屬性,然后才是類。

利用這些技術把屬性儲存在不同對象內,我們可以決定其可見范圍。附加在類上時,變量名是共享的;附加在實例上時,變量名是屬于每個實例的數據,而不是共享的數據。

方法

方法即函數。方法在class中是由def語句創建的函數對象。從抽象的角度來看,方法替實例對象提供了要繼承的行為。從程序的角度看,方法與簡單函數的工作方式完全一致,只是有一個重要的差別:方法的第一個參數總是接收方法調用的隱性主體,也就是實例對象。

Python會自動把實例方法的調用對應到類方法函數。如下所示,方法調用需要通過實例,就像這樣:

instance.method(args...)

這會自動翻譯成以下形式的類方法函數調用:

class.method(instance,args...)

class通過Python繼承搜索流程找出方法名稱所在之處。事實上,兩種調用形式在Python中都有效。

在類方法中,按慣例第一個參數通常都稱為self(嚴格來說,只有其位置重要,而不是它的名稱)。這個參數給方法提供了一個鉤子,從而返回調用的主體,也就是實例對象:因為類可以產生許多實例對象,所以需要這個參數來慣例每個實例彼此各不相同的數據。

例子

定義下面這個類:

>>> class NextClass:
  def printer(self,text):
    self.message = text
    print(self.message)

我們通過實例調用printer方法如下:

>>> x = NextClass()
>>> x.printer('instance call')
instance call
>>> x.message
'instance call'

當通過實例進行點號運算調用它時,printer會先通過繼承將其定位,然后它的self參數會自動賦值為實例對象(x)。text參數會獲得在調用時傳入的字符串('instance call')。注意:因為Python會自動傳遞第一個參數給self,實際上只需要傳遞一個參數。在printer中,變量名self是用于讀取或設置每個實例的數據的,因為self引用的是當前正在處理的實例。

方法能通過實例或類本身兩種方法其中的任意一種進行調用。例如,我們也可以通過類的名稱調用printer,只要明確地傳遞了一個實例給self參數。

>>> NextClass.printer(x,'class call')#Direct Class Call
class call
>>> x.message
'class call'

通過實例和類的調用具有相同的效果,只要在類形式中傳遞了相同的實例對象。實際上,在默認情況下,如果嘗試不帶任何實例調用的方法時,就會得到出錯信息。

>>> NextClass.printer('bad call')
Traceback (most recent call last):
 File "<pyshell#35>", line 1, in <module>
  NextClass.printer('bad call')
TypeError: printer() missing 1 required positional argument: 'text'

調用超類構造函數

在構造時,Python會找出并且只調用一個__init__。如果保證子類的構造函數也會執行超類構造時的邏輯,一般都必須通過類明確地調用超類的__init__方法。

class Super:
  def __init__(self,x):
    ...default code...
class Sub(Super):
  def __init__(self,x,y):
    Super.__init__(self,x)
    ...custom code...
I = Sub(1,2)

這種寫法便于維護代碼,之前也介紹過。這種方法擴展了超類的方法,而不是完全取代了它。

類接口技術

擴展只是一種與超類接口的方法。下面所示的specialize.py文件定義了多個類,示范了一些常用技巧。

Super:定義一個method函數以及在子類中期待一個動作的delegate。
Inheritor:沒有提供任何新的變量名,因此會獲得Super中定義的一切內容。
Replacer:用自己的版本覆蓋Super的method
Extender:覆蓋并回調默認method,從而定制Super的method
Provider:實現Super的delegate方法預期的action方法。

下面是這個文件:

class Super:
  def method(self):
    print('in Super.methon')
  def delegate(self):
    self.action()
class Inheritor(Super):
  pass
class Replacer(Super):
  def method(self):
    print('in Replacer.method')
class Extender(Super):
  def method(self):
    print('starting Extender.method')
    Super.method(self)
    print('ending Extender.method')
class Provider(Super):
  def action(self):
    print('in Provider.action')
if __name__=='__main__':
  for klass in (Inheritor,Replacer,Extender):
    print('\n'+klass.__name__+'...')
    klass().method()
  print('\nProvider...')
  x = Provider()
  x.delegate()

執行結果如下:

Inheritor...
in Super.methon
Replacer...
in Replacer.method
Extender...
starting Extender.method
in Super.methon
ending Extender.method
Provider...
in Provider.action

抽象超類

注意上例中的Provider類是如何工作的。當通過Provider實例調用delegate方法時,有兩個獨立的繼承搜索會發生:

1.在最初的x.delegate的調用中,Python會搜索Provider實例和它上層的對象,直到在Super中找到delegate的方法。實例x會像往常一樣傳遞給這個方法的self參數。

2.在Super.delegate方法中,self.action會對self以及它上層的對象啟動新的獨立繼承搜索。因為self指的是Provider實例,在Provider子類中就會找到action方法。

這種“填空式”的代碼結構一般就是OOP的軟件框架。這個例子中的超類有時也稱作是抽象超類——也就是類的部分行為默認是由其子類所提供的。如果預期的方法沒有在子類中定義,當繼承搜索失敗時,Python會引發未定義變量名的異常。

感謝各位的閱讀!關于“Python面向對象類如何編寫”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

博爱县| 东丽区| 阜新| 定边县| 清远市| 鱼台县| 铜陵市| 桃园市| 长乐市| 临湘市| 东乡族自治县| 潜江市| 黄大仙区| 定远县| 咸宁市| 新营市| 安康市| 元阳县| 张家川| 呼伦贝尔市| 肇庆市| 自贡市| 德格县| 英德市| 醴陵市| 池州市| 和龙市| 康保县| 镇巴县| 通许县| 阳曲县| 永宁县| 武义县| 从江县| 瓦房店市| 西和县| 常州市| 英吉沙县| 濮阳市| 澄迈县| 前郭尔|