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

閱讀 14:40·字數 4403·更新 
Youtube 頻道
訂閱 130

先決條件

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

定義 Python 類別

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

class <classname>:
    <docstring>
    <block>

classname 部分

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

docstring 部分

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

block 部分

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

Python 類別的特性

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

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

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

apple.py
# 一個簡單的類別 Apple
class Apple:
	# 變數 variety
	variety = '普通蘋果'
	# 靜態方法 show
	@staticmethod
	def show():
		print(Apple.variety)

# 為特性 variety 指派 Apple.variety = '石頭蘋果' # 呼叫 show 方法 Apple.show()
石頭蘋果

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

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

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

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

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

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

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

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

我們調整之前的範例,為類別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}

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

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

在下面的程式碼中,書寫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 類別的變數

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

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

variablename 部分

variablename為變數名稱,他需要符合 Python 的識別碼規格,不能使用 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 類別的方法

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

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

methname 部分

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

parameterlist 部分

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

block 部分

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

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

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

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

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

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

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

函式

想要深入了解 Python 函式,你可以檢視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 類別的私用特性

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

Python 類別的私用特性識別碼會自動增加首碼

__開頭的私用特性,其識別碼會自動增加特定首碼,其內容為_與類別名稱的組合,這一現象可通過 Python 類別或 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 類別的建構子

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

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

建立 Python 類別的執行個體

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

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

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

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

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

Python 類別的命名空間

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

命名空間,有效範圍

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

Python 類別的文件字串

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

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

Python 巢狀類別

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

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

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

內容分類

程式碼

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