URLhttps://learnscript.net/zh-hant/python/classes/
    複製連結移至說明  範例

    Python 類別介紹,以及定義和使用類別

    閱讀 14:23·字數 4318·更新 
    Youtube 頻道
    訂閱 375

    先決條件

    閱讀本節的先決條件是已經掌握類別的相關概念,你可以檢視程式設計教學物件導向程式設計,類別,執行個體介紹一節來了解他們。

    定義 Python 類別

    在 Python 中,類別通常被定義在模組中,其語法的基本形式如下。

    class <classname>:
        <docstring>
        <block>

    classname 部分

    classname為類別的名稱,他需要符合 Python 的識別碼規格,不能使用關鍵字或保留關鍵字。

    docstring 部分

    docstring是類別的文件字串,包含了對類別的說明,這並非強製性的要求,一個類別可以沒有文件字串。

    block 部分

    block為類別的主體程式碼,他和docstring都需要使用某種空白字元進行縮排,以表示其歸屬於類別。

    Python 類別的特性

    與模組類似,在類別中定義的變數(欄位),屬性,方法(函式)等內容,被稱為特性(Attribute)。特性可通過形式類似於c.namec.name=value的運算式進行存取,其中c為類別或物件(類別的執行個體),name為特性(名稱,識別碼),value為特性的新值。

    當然,類別的特性可以被稱呼為變數,方法,屬性,這並沒有什麽問題。

    下面是一個簡單的類別Apple,包含變數和靜態方法。

    apple.py
    # 一個簡單的類別 Apple
    class Apple:
    	# 變數 variety
    	variety = '普通蘋果'
    	# 靜態方法 show
    	@staticmethod
    	def show():
    		print(Apple.variety)
    
    # 為特性 variety 指派 Apple.variety = '石頭蘋果' # 呼叫 show 方法 Apple.show()
    石頭蘋果

    Python 的類別特性和執行個體特性

    在 Python 中,類別的特性分為類別特性和執行個體特性,類別特性直接在類別中定義,或通過表示類別的參數(一般約定為cls)來定義,而執行個體特性則需要通過執行個體,或表示執行個體的參數(一般約定為self)來定義。

    類別特性可通過類別或表示類別的參數(一般約定為cls),以及執行個體或表示執行個體的參數(一般約定為self)來存取,而執行個體特性則只能通過執行個體或表示執行個體的參數來存取。

    為類別或執行個體新增暫時特性

    在沒有限製的情況下,一個類別或執行個體可以新增暫時存在的特性,只需要使用形式為c.name=value的運算式即可,其中c為類別或執行個體,name為新增的特性(名稱,識別碼),value為特性的值。

    如何檢視類別或執行個體的所有特性?

    通過類別,執行個體,物件的特殊特性__dict__,你可以檢視其對應的所有特性,包括私用特性和暫時特性在內。__dict__是一個字典物件,其中鍵值組的鍵表示特性的名稱,鍵值組的值表示特性的具體內容。

    需要指出的是,類別的__dict__與執行個體的__dict__中的鍵值組不會重疊,類別的__dict__僅包含類別特性,執行個體的__dict__僅包含執行個體特性,不過,不排除存在分別歸屬於類別和執行個體的同名特性。

    我們調整之前的範例,為類別Apple新增建構子以定義執行個體變數weight,並通過類別新增暫時類別變數price,通過執行個體新增暫時執行個體變數price,然後輸出顯示Apple類別和執行個體的__dict__特性。

    apple.py
    # 一個簡單的類別 Apple
    class Apple:
    	# …
    	# 建構子
    	def __init__(self, w):
    		# 通過表示執行個體的 self 定義了執行個體變數 weight
    		self.weight = w
    # …
    # 為 Apple 類別新增一個類別變數,然後顯示 Apple 類別的所有特性
    Apple.price = 10
    print(Apple.__dict__)
    # 為執行個體新增一個執行個體變數,然後顯示執行個體的所有特性
    apple = Apple(100)
    apple.price = 30
    print(apple.__dict__)
    {'__module__': '__main__', 'variety': '石頭蘋果', 'show': <staticmethod(<function Apple.show at >)>, '__init__': <function Apple.__init__ at >, '__dict__': <attribute '__dict__' of 'Apple' objects>, '__weakref__': <attribute '__weakref__' of 'Apple' objects>, '__doc__': None, 'price': 10}
    {'weight': 100, 'price': 30}

    不能通過執行個體來直接指派修改類別特性

    你可以通過執行個體或表示執行個體的參數(比如self)來讀取類別特性,但無法進行指派操作,因為指派操作將被認為是向執行個體增加新的特性,這類似於試圖在函式中直接指派模組定義的變數。

    在下面的程式碼中,書寫apple.variety等同於讀取Apple.variety,書寫apple.variety='超大蘋果'等同於為執行個體apple新增執行個體變數varietyApple.variety不會被修改。

    apple.py
    # …
    # 建立 Apple 類別的執行個體
    apple = Apple(30)
    # 通過執行個體存取類別變數 variety
    print(apple.variety)
    
    # 下面的指派陳述式將為執行個體定義新的執行個體變數 variety apple.variety = '超大蘋果' # 因此,類別變數 variety 並沒有變化 print(Apple.variety)
    石頭蘋果
    石頭蘋果

    定義 Python 類別的變數

    類別的變數(欄位)分為類別變數和執行個體變數,他是類別的特性之一,你可以通過以下形式來定義類別變數或執行個體變數,其中,cls為表示類別的參數,self為表示執行個體的參數。

    [cls|self.]<variablename>=<value>

    variablename 部分

    variablename為變數名稱,他需要符合 Python 的識別碼規格,不能使用關鍵字或保留關鍵字。

    value 部分

    value為變數對應的值。

    student.py
    # 一個表示學生的類別 Student
    class Student:
    	# 類別變數 count
    	count = 0
    	# 建構子
    	def __init__(self, n, a):
    		# 執行個體變數 name,age
    		self.name = n
    		self.age = a

    定義 Python 類別的方法

    類別的方法(函式)是類別的特性之一,他與模組中的函式有相似之處,可通過如下形式進行定義,其中,@classmethod表示定義類別方法,@staticmethod表示定義靜態方法。

    [@classmethod|@staticmethod]
    def <methname>(<parameterlist>)
        <block>

    methname 部分

    methname為方法名稱,他需要符合 Python 的識別碼規格,不能使用關鍵字或保留關鍵字。

    parameterlist 部分

    parameterlist是方法的參數串列,他定義了方法的所有參數,參數之間使用,進行分隔。

    block 部分

    block為方法的主體程式碼,需要使用某種空白字元進行縮排,以表示其歸屬於方法。

    如果未指定修飾詞@classmethod@staticmethod,則定義的方法被稱為執行個體方法,其第一個參數一般命名為self,表示執行個體本身,通過該參數可讀取寫入執行個體特性,或讀取類別特性。當通過執行個體呼叫執行個體方法時,需要省去self參數,當通過類別呼叫執行個體方法時,需要給出self參數。

    如果指定了修飾詞@classmethod,則定義的方法為類別方法,其第一個參數一般命名為cls,表示類別本身,通過該參數可以存取類別特性,但不能存取執行個體特性。無論是通過執行個體還是類別,呼叫類別方法時都需要省去cls參數。

    如果指定了修飾詞@staticmethod,則定義的方法為靜態方法,靜態方法不像執行個體方法或類別方法一樣擁有特殊參數,因此他不能通過特殊參數來存取執行個體特性或類別特性。

    直接定義在類別中的方法均為類別特性

    事實上,直接定義在類別中的方法均為類別特性,而非執行個體特性,無論這些方法被稱為執行個體方法,類別方法還是靜態方法,他們之間的主要區別在於,首個參數表示的是執行個體還是類別,或均不表示。

    也正因為都是類別特性,執行個體方法,類別方法,靜態方法既可以通過 執行個體呼叫,也可以通過類別呼叫。

    函式

    想要深入了解 Python 函式,你可以檢視Python 函式,參數,傳回值介紹,以及函式的定義和呼叫一節。

    下面,我們為之前的Student類別增加一些方法,並分別通過類別或執行個體來呼叫他們。

    student.py
    # 一個表示學生的類別 Student
    class Student:
    	# …
    	# 執行個體方法 info
    	def info(self):
    		print(f'{self.name} {self.age}')
    
    # 類別方法 show @classmethod def show(cls): # 通過參數 cls 讀取類別變數 count print(f'一共 {cls.count} 個學生') # 靜態方法 set_count @staticmethod def set_count(c): # 只能通過類別存取類別變數 Student.count = c print(f'學生數量被設定為 {Student.count}')
    student = Student('小小', 13) # 呼叫執行個體方法 info student.info() Student.info(student) # 呼叫靜態方法 set_count student.set_count(-100) Student.set_count(100) # 呼叫類別方法 show student.show() Student.show()
    小小 13
    小小 13
    學生數量被設定為 -100
    學生數量被設定為 100
    一共 100 個學生
    一共 100 個學生

    定義 Python 類別的私用特性

    無論是類別特性還是執行個體特性,如果識別碼以__開頭,則這些特性即為私用特性,只能在定義他們的類別中存取,不能在外部或衍生類別中存取。

    類別的私用特性識別碼會自動增加前綴

    __開頭的私用特性,其識別碼會自動增加特定前綴,其內容為_與類別名稱的組合,這一現象可通過類別或執行個體的__dict__特性來觀察。識別碼的改動僅涉及定義特性的類別,這也就是無法在外部或衍生類別中使用私用特性的原因,因為你在存取一個並不存在的內容。

    當然,在了解以上規則後,私用特性可能變得不再私用,只需要采用具有特定前綴的識別碼進行存取即可。

    下面的類別Teacher定義了兩個私用的執行個體變數,他們的識別碼自動新增了前綴_Teacher

    teacher.py
    # 一個表示教師的類別 Teacher
    class Teacher:
    	# 建構子
    	def __init__(self, n, a):
    		# 私用執行個體變數 __name,__age
    		self.__name = n
    		self.__age = a
    
    teacher = Teacher('隱者', 30) # 顯示 Teacher 執行個體的所有特性 print(teacher.__dict__) # 使用特殊方式存取私用變數 __name print(teacher._Teacher__name)
    {'_Teacher__name': '隱者', '_Teacher__age': 30}
    隱者

    定義 Python 類別的建構子

    類別的建構子是一個名為__init__的執行個體方法,與其他執行個體方法一樣,__init__方法的第一個參數一般命名為self,表示執行個體自身,其余參數可用於初始化執行個體變數或執行其他操作,就如同Student類別所作的那樣。

    當然,在官方文件中,並沒有建構子這樣的說法,__init__的含義僅為初始化,他在執行個體建立後被呼叫。

    建立 Python 類別的執行個體

    要建立類別的執行個體,你需要使用類別名稱和()()包含了一組參數,這些參數一般與__init__方法的參數一致(需要省去self)。比如,之前範例中使用Student('小小',13)建立了Student類別的執行個體。

    如何檢視執行個體對應的型別?

    通過執行個體(物件)的__class__屬性(Property),可以取得該執行個體對應的型別(類別)資訊,__class__屬性的傳回值是一個type物件。

    對於已定義的類別來說,__class__屬性的傳回值顯示為<class 'type'>,這表示已定義的類別可被視為執行個體,其型別是type

    student.py
    # …
    # 取得 Student 類別和之前建立的執行個體 student 的型別資訊
    print(student.__class__)
    print(Student.__class__)
    <class '__main__.Student'>
    <class 'type'>

    Python 類別的命名空間

    理所當然的,類別應該擁有自己的命名空間,以避免類別所擁有的特性的識別碼與其他識別碼沖突。

    命名空間,有效範圍

    想要深入了解命名空間和有效範圍,你可以檢視程式設計教學命名空間,有效範圍介紹一節。

    Python 類別的文件字串

    與函式和模組類似,類別也具有儲存在__doc__中的文件字串,他是字串常值,是類別的第一行有效程式碼,可以采用緊密相鄰或加入空白字元的方式進行拼接,不包含需要運算的內容或操作。

    hello.py
    # 一個奇怪的類別
    class Hello:
    	"""你好啊,"""'Python!'

    Python 巢狀類別

    巢狀類別是定義在另一個類別,函式或方法中的類別。由於有效範圍的一般性原則,被定義的巢狀類別的可存取性,等同於同一命名空間中定義的變數。

    下面定義的巢狀類別World,其可存取性等同於Hello中的類別變數。

    hello.py
    # 一個奇怪的類別
    class Hello:
    	# …
    	# 一個奇怪的巢狀類別
    	class World:
    		pass

    內容分類

    原始碼

    src/zh-hant/classes·codebeatme/python·GitHub