全網最適合入門的物件導向程式設計教程:03 類和物件的Python實現-為自定義類新增屬性

FreakStudio發表於2024-06-28

摘要:

本文主要介紹了,當使用 Python 建立自定義類時,如何為其新增屬性,包括為類和例項新增屬性兩種,以及如何獲取自定義的屬性等內容。

往期推薦:

學嵌入式的你,還不會物件導向??!

全網最適合入門的物件導向程式設計教程:00 物件導向設計方法導論

全網最適合入門的物件導向程式設計教程:01 物件導向程式設計的基本概念

全網最適合入門的物件導向程式設計教程:02 類和物件的 Python 實現-使用 Python 建立類

更多精彩內容可看:

給你的 Python 加加速:一文速通 Python 平行計算

一文搞懂 CM3 微控制器除錯原理

肝了半個月,嵌入式技術棧大彙總出爐

電子計算機類比賽的“武林秘籍”

一個MicroPython的開源專案集錦:awesome-micropython,包含各個方面的Micropython工具庫

文件和程式碼獲取

可訪問如下連結進行對文件下載:

https://github.com/leezisheng/Doc

image

本文件主要介紹如何使用 Python 進行物件導向程式設計,需要讀者對 Python 語法和微控制器開發具有基本瞭解。相比其他講解 Python 物件導向程式設計的部落格或書籍而言,本文件更加詳細、側重於嵌入式上位機應用,以上位機和下位機的常見串列埠資料收發、資料處理、動態圖繪製等為應用例項,同時使用 Sourcetrail 程式碼軟體對程式碼進行視覺化閱讀便於讀者理解。

相關示例程式碼獲取連結如下:https://github.com/leezisheng/Python-OOP-Demo

正文

類自身可以具有自己的屬性,被稱為類屬性,或者類成員變數。我們可以透過點標記法在不改動類定義的情況下為例項物件設定任意屬性:

_# 建立一個串列埠類_
class SerialClass:
    pass

_# 生成串列埠類的例項_
serdev = SerialClass()
_# 新增屬性-串列埠裝置名_
serdev.devport      = "COM17"
_# 新增屬性-波特率_
serdev.devbaudrate  = 115200
_# 新增屬性-資料位_
serdev.devbytesize  = 8
_# 新增屬性-校驗位_
serdev.devparity    = 0
_# 新增屬性-停止位_
serdev.devstopbits  = 1
_# __dict__可以動態的獲取到物件的全部屬性_
print(serdev.__dict__)

以上程式碼建立了一個空的 SerialClass 類,沒有任何資料或行為。然後建立了這個類的兩個例項並分別賦予它們串列埠裝置名、波特率、資料位等串列埠相關的屬性並賦值。

為物件屬性賦值的語法是 < 物件.< 屬性=< 值 >

這種方法被稱為點標記法(dot notation)。這裡的值可以是任何型別:Python 的基本型別、內建資料型別或者其他的物件,甚至可以是一個函式或另一個類!

最後透過__dict__,就可以動態的獲取到物件的全部屬性,__dict__返回一個字典,屬性名是字典的 key,屬性值是字典的 value。

我們也可以對類屬性賦值,方法同上,程式碼如下:

_# 建立一個串列埠類_
class SerialClass:
    pass

_# 新增屬性-串列埠裝置名_
SerialClass.devport      = "COM17"
_# 新增屬性-波特率_
SerialClass.devbaudrate  = 115200
_# 新增屬性-資料位_
SerialClass.devbytesize  = 8
_# 新增屬性-校驗位_
SerialClass.devparity    = 0
_# 新增屬性-停止位_
SerialClass.devstopbits  = 1
_# __dict__可以動態的獲取到物件的全部屬性_
print(SerialClass.__dict__)

_# 生成串列埠類的例項_
serdev = SerialClass()
print(serdev.devport)
print(serdev.devbaudrate)
print(serdev.devbytesize)
print(serdev.devparity)
print(serdev.devstopbits)

image

可以看到,對類屬性賦予新的值,它的所有例項的類屬性也會更新。實際上,類屬性在建立例項時並不會被單獨建立,都是引用的類的屬性,它們在記憶體中只有一份。

同樣我們可以透過例項來改變類屬性,此時將進行複製動作,該例項的類屬性將脫離類的屬性,實現了屬性的解繫結,把原來類屬性覆蓋了,該屬性成為了例項的私有屬性,其他例項不會受影響

serdev.devport = "COM15"
print(serdev.devport)
print(SerialClass.devport)

image

在實際的使用時,類屬性應該只用於類相關的描述,類示例可以訪問和使用它們,但不應該更改它們。

由於類可以起到模板的作用,因此,可以在建立例項的時候,把一些我們認為必須繫結的屬性強制填寫進去。透過定義一個特殊的__init__方法,在建立例項的時候,就把 devport,devbaudrate 等屬性綁上去:

_# 建立一個串列埠類_
class SerialClass:
    _# 注意:特殊方法“__init__”前後分別有兩個下劃線!!!_
    def __init__(self,port,baudrate,bytesize,parity,stopbits):
        self.devport        = port
        self.devbaudrate    = baudrate
        self.devbytesize    = bytesize
        self.devparity      = parity
        self.devstopbits    = stopbits

_# 生成串列埠類的例項_
serdev = SerialClass(port     = "COM17",
                     baudrate = 115200,
                     bytesize = 8,
                     parity   = 0,
                     stopbits = 1
                    )

init 方法的第一個引數永遠是 self,表示建立的例項本身,因此,在 init 方法內部,就可以把各種屬性繫結到 self,因為 self 就指向建立的例項本身。有了 init 方法,在建立例項的時候,就不能傳入空的引數了,必須傳入與 init 方法匹配的引數,但 self 不需要傳,Python 直譯器自己會把例項變數傳進去。
image

相關文章