《從零開始的Python筆記》Day#6:物件導向設計

更新於 發佈於 閱讀時間約 18 分鐘
raw-image

大部分在學習程式語言的人很常會看到或是聽到一個很抽象的詞:物件導向

對於初學者來說,又出現了一個很難以理解的名詞,而且在學習上的確也是很常讓人碰壁的一部分。雖然有著不小的學習障礙,但是對於提升程式設計能力有很大的幫助,因此建議大家可以多點耐心去接觸並且練習如何使用它。

🧱 物件導向程式設計(OOP)

為了掌握Python 的物件導向程式設計,需要了解類別與物件的基本概念,熟悉繼承、多型,以及封裝的應用,並理解特殊方法如 __init__、__str__ 等的使用。

為什麼要學物件導向程式設計?

假設你是一名在銀行工作的工程師,負責為新開戶的顧客建立他們的帳號,並設計一系列帳戶功能(如存款、提款、查詢餘額等)。一開始,如果單純依賴傳統的程式設計方法(例如手動寫程式碼處理每位顧客的帳戶),當有 100 位顧客時,你需要重複撰寫 100 次類似的程式碼,導致浪費大量時間,且不易維護。

然而,有沒有更有效率、更易於擴展的方法?

💡 答案是:利用物件導向設計(OOP)!

物件導向程式設計(OOP, Object-Oriented Programming) 是目前主流的程式設計架構之一。OOP 通過將程式碼結構化為抽象的物件,更高效地組織和管理複雜的業務邏輯。這種設計理念提供了類別(Class)與物件(Object)的架構,可以模擬真實世界中的實體與行為(例如人物、動作、資源等),使程式的設計更符合直觀的現實模型。

優點:

  1. 提升模組化與重用性:類別和物件讓程式開發更具模組化,可以輕鬆地複用代碼,減少重複撰寫的工作
  2. 促進代碼可維護性:把邏輯封裝成類別和方法後,改動某一部分不會影響其他部分,便於維護
  3. 資料封裝:通過封裝(如私有屬性)保護數據不被外部直接修改,增強代碼穩定性
  4. 支援繼承與多型:輕鬆改進現有邏輯(繼承),並根據需求多態化物件的行為
  5. 真實世界建模:物件導向的架構可以很自然地模擬真實對象和系統行為(如銀行帳戶、圖書館管理等)

缺點:

  1. 學習曲線較高:對初學者來說,掌握類別、物件、繼承、多型等概念需要一定的學習時間
  2. 過度設計的風險:小型項目中過度使用 OOP 可能導致複雜而臃腫的架構,降低生產率
  3. 性能考慮:相較於程序式(動態代碼的不斷執行),OOP 有時因需處理更多結構化代碼而稍顯慢速

📦 類別與物件

定義類別與建立物件

  • 類別 (Class) 是物件的藍圖或模板,
  • 物件 (Object) 是類別的實例。透過類別定義屬性和方法,並根據類別創建物件。
  • 可以快速建立相同類別的物件
    • 如:銀行新戶是類別,新戶小明是物件

定義類別

class Person:
"""這是一個描述人的類別"""
pass

# 建立物件
person1 = Person()person2 = Person()print(person1) # <__main__.Person object at ...>
print(person2) # <__main__.Person object at ...>

類別的屬性與方法

  • 屬性 (Attributes) 是描述物件的資料或特性,方法 (Methods) 是對象可以執行的動作。
  • 物件本身具有的特性以及可以做的事情
    • 如:銀行新戶小明具有零存款,預計存入100萬。- 具有零存款:屬性- 存入100萬:方法

__init__初始化方法

  • __init__ 是類別的 建構函數,在建立物件時自動執行,用於初始化屬性。
  • 先預設的屬性,之後還可以修改

銀行開戶範例

  1. 初始化方法屬性: (1) 銀行戶名屬性 (2) 存款餘額
  2. 存款方法
  3. 自定義print()資訊
  4. 為小明創建帳戶
  5. 小明存入100萬
class BankAccount:
def __init__(self, name, balance=0):
"""
初始化方法,用於建立銀行帳戶
:param name: 新戶名(例如小明)
:param balance: 初始存款額度,預設為 0
"""
self.name = name
self.balance = balance

def deposit(self, amount):
"""
存款方法,將指定金額存入帳戶
:param amount: 存入的金額
"""
if amount > 0: # 檢查存入金額是否有效
self.balance += amount
print(f"{self.name} 存入 {amount} 元。當前餘額為: {self.balance} 元。")
else:
print("存入金額必須大於 0!")

def __str__(self):
"""
自訂字串方法,提供帳戶資訊的友好表示
"""
return f"戶名: {self.name}, 存款餘額: {self.balance} 元"

# 創建新的銀行帳戶物件(小明)
xiaoming = BankAccount(name="小明")

# 初始化訊息
print(xiaoming) # 戶名: 小明, 存款餘額: 0 元

# 小明存入 100 萬
xiaoming.deposit(1000000)

🧬 繼承與多型

父類別與子類別

  • 繼承允許我們基於一個父類別 (Parent Class) 建立一個子類別 (Child Class)
  • 子類別可以繼承父類別的屬性與方法
  • 可以大幅減少重複的程式碼
    • 寫過的功能不要再寫一遍
class Animal:
"""父類別:描述動物"""
def __init__(self, name):
self.name = name

def speak(self):
print(f"{self.name} makes a sound.")

class Dog(Animal):
"""子類別:描述狗"""
def speak(self):
print(f"{self.name} barks.")

class Cat(Animal):
"""子類別:描述貓"""
def speak(self):
print(f"{self.name} meows.")

# 建立物件
dog = Dog("Rover")
cat = Cat("Whiskers")

# 呼叫方法
dog.speak() # Rover barks.
cat.speak() # Whiskers meows.

方法覆寫(Override)

  • 子類別可以通過覆寫父類別的方法來實現自己的行為。
  • 但是可以透過覆寫來修改原本繼承的功能
    • 同樣都是speak()方法,但是功能已經不同
class Animal:
"""父類別"""
def speak(self):
print("An animal makes a sound.")

class Dog(Animal):
"""子類別"""
def speak(self):
print("The dog barks.")

# 建立物件
animal = Animal()
dog = Dog()

# 呼叫方法
animal.speak() # An animal makes a sound.
dog.speak() # The dog barks

🔒 封裝、私有屬性與特殊方法

使用 _ 與 __ 定義私有屬性

  • 單底線 _:表示「非公開」屬性,但仍可存取(是一種約定)。
  • 雙底線 __:觸發名稱重整 (Name Mangling),將屬性名稱改為 _ClassName__attribute,避免外部直接訪問。
    • 避免重要屬性被隨意修改
class BankAccount:
def __init__(self, account_owner, balance):
self.account_owner = account_owner
self.__balance = balance # 私有屬性

def deposit(self, amount):
self.__balance += amount

def __str__(self):
return f"{self.account_owner} - Balance: ${self.__balance}"

# 建立物件
account = BankAccount("Alice", 1000)

# 存款
account.deposit(500)
print(account) # Alice - Balance: $1500

# 嘗試直接訪問私有屬性
# print(account.__balance) # AttributeError: 'BankAccount' object has no attribute '__balance'

特殊方法(Advanced)

特殊方法是Python的進階語法,初學者可以不需要會用,但是要看的懂他在幹什麼,因為在欣賞(Trace code)其他人程式時會很常看到相關的用法。

__str__ & __repr__: 描述

  • __str__:用於定義 人類可讀的描述,當 print() 或 str() 被調用時自動執行
  • __repr__:用於定義 開發者可讀的描述,當在解釋器中回傳對象或執行 repr() 時被呼叫,為開發者提供精確相關的描述
class Person:
def __init__(self, name, age):
self.name = name
self.age = age

def __str__(self):
return f"Person(name={self.name}, age={self.age})"

def __repr__(self):
return f"<Person: {self.name}, {self.age} years old>"

# 建立物件
person = Person("Alice", 25)

# 呼叫
print(person) # 自動調用 __str__: Person(name=Alice, age=25)
print(repr(person)) # 顯示開發者可讀描述: <Person: Alice, 25 years old>

__del__:銷毀

  • 在 對象被刪除或清理時呼叫,用於釋放資源
  • 通常不需要顯式使用,Python 的垃圾回收機制會自動處理
class Resource:
def __init__(self, name):
self.name = name
print(f"Resource {self.name} created.")

def __del__(self):
print(f"Resource {self.name} destroyed.")

# 創建並銷毀對象
res = Resource("File")
del res # Resource File destroyed.

__getattr__ 與 __setattr__:屬性管理

  • __getattr__: 當訪問一個未定義的屬性時自動呼叫。
  • __setattr__: 每次設定屬性時自動呼叫,用於攔截屬性賦值。
class ManagedAttributes:
def __init__(self):
self.attributes = {}

def __getattr__(self, name):
return self.attributes.get(name, f"{name} not found!")

def __setattr__(self, name, value):
if name == "attributes": # 防止遞歸調用
super().__setattr__(name, value)
else:
self.attributes[name] = value
print(f"Set {name} to {value}")

# 使用示例
obj = ManagedAttributes()
obj.foo = 42 # Set foo to 42
print(obj.foo) # 42
print(obj.bar) # bar not found!

__len__:定義對象長度

  • 定義對象的「長度」,用於 len() 函數
  • 很常使用的一個方法
class Bookshelf:
def __init__(self, books):
self.books = books

def __len__(self):
return len(self.books)

shelf = Bookshelf(["Book1", "Book2", "Book3"])
print(len(shelf)) # 3

__getitem__ 與 __setitem__:Item操作

  • __getitem__:支持通過對象的下標運算(如 obj[key])。
  • __setitem__:支持對象的下標賦值(如 obj[key] = value)。
  • 此方法常見於機器學習和深度學習中的Dataloader函數
class Storage:
def __init__(self):
self.data = {}

def __getitem__(self, key):
return self.data.get(key, None)

def __setitem__(self, key, value):
self.data[key] = value
print(f"Set {key} to {value}")

# 使用示例
storage = Storage()
storage["name"] = "Alice" # Set name to Alice
print(storage["name"]) # Alice

__call__:可調用對象

  • 使對象變成「可調用」,像函數一樣使用
  • 在許多深度學習的模型建立架構中可見到
class Counter:
def __init__(self):
self.count = 0

def __call__(self):
self.count += 1
print(f"Count: {self.count}")

# 使用示例
counter = Counter()
counter() # Count: 1
counter() # Count: 2

__add__ : 運算符

  • 支持重新定義運算符,如 +(加法)、-(減法)、*(乘法)等
  • 可用於自定義運算功能
class Number:
def __init__(self, value):
self.value = value

def __add__(self, other):
return Number(self.value + other.value)

def __str__(self):
return str(self.value)

num1 = Number(10)
num2 = Number(20)

result = num1 + num2
print(result) # 30










留言
avatar-img
留言分享你的想法!
avatar-img
Ethan的AI學習筆記
1會員
23內容數
我是一個不務正業的資料科學家,從零開始學習的路途上跌跌撞撞,跌過許多坑,也撞過許多牆... 當有人迷失方向時,希望這些筆記可以成為你的指南針。
Ethan的AI學習筆記的其他內容
2025/08/14
學習到這個階段,大家如果都有跟上的話已經可以試著自行開發一些工具或是演算法了。不過Python還有提供許多進階的功能可以幫助我們在開發的過程中更順暢、更有效率。 ⚠️ 例外處理 (Exception)
Thumbnail
2025/08/14
學習到這個階段,大家如果都有跟上的話已經可以試著自行開發一些工具或是演算法了。不過Python還有提供許多進階的功能可以幫助我們在開發的過程中更順暢、更有效率。 ⚠️ 例外處理 (Exception)
Thumbnail
2025/08/13
學完Python的基礎課程後,大家對於Python已經有了一定程度的了解,可以開始踏入Python進階的課程了! 這邊將介紹 Python 中的函數、模組與套件,這些技巧可以提升結構化、模組化程式的能力,讓程式碼更易於維護、重用與共享。
Thumbnail
2025/08/13
學完Python的基礎課程後,大家對於Python已經有了一定程度的了解,可以開始踏入Python進階的課程了! 這邊將介紹 Python 中的函數、模組與套件,這些技巧可以提升結構化、模組化程式的能力,讓程式碼更易於維護、重用與共享。
Thumbnail
2025/08/09
資料結構是程式設計的核心基石,直接影響演算法的效率與軟體設計的品質。在開發軟體工具時,選擇合適的資料結構不僅是解決問題的關鍵,也是實現高效與穩健程式的重要步驟。 Python 提供了多樣化的內建資料結構,每一種結構都針對特定的任務情境進行了優化設計。接下來,我們將深入探討這些資料結構的特性與用法,
Thumbnail
2025/08/09
資料結構是程式設計的核心基石,直接影響演算法的效率與軟體設計的品質。在開發軟體工具時,選擇合適的資料結構不僅是解決問題的關鍵,也是實現高效與穩健程式的重要步驟。 Python 提供了多樣化的內建資料結構,每一種結構都針對特定的任務情境進行了優化設計。接下來,我們將深入探討這些資料結構的特性與用法,
Thumbnail
看更多
你可能也想看
Thumbnail
2025 vocus 推出最受矚目的活動之一——《開箱你的美好生活》,我們跟著創作者一起「開箱」各種故事、景點、餐廳、超值好物⋯⋯甚至那些讓人會心一笑的生活小廢物;這次活動不僅送出了許多獎勵,也反映了「內容有價」——創作不只是分享、紀錄,也能用各種不同形式變現、帶來實際收入。
Thumbnail
2025 vocus 推出最受矚目的活動之一——《開箱你的美好生活》,我們跟著創作者一起「開箱」各種故事、景點、餐廳、超值好物⋯⋯甚至那些讓人會心一笑的生活小廢物;這次活動不僅送出了許多獎勵,也反映了「內容有價」——創作不只是分享、紀錄,也能用各種不同形式變現、帶來實際收入。
Thumbnail
Python資料視覺化在數據分析中扮演關鍵角色,透過視覺化捕捉數據模式、趨勢和異常,透過Matplotlib等工具創建專業圖表變相對簡單和高效。
Thumbnail
Python資料視覺化在數據分析中扮演關鍵角色,透過視覺化捕捉數據模式、趨勢和異常,透過Matplotlib等工具創建專業圖表變相對簡單和高效。
Thumbnail
這一節談的是向量的定義,以及如何運用向量來建立模擬物體運動時,關於位置和速度間的關係式。
Thumbnail
這一節談的是向量的定義,以及如何運用向量來建立模擬物體運動時,關於位置和速度間的關係式。
Thumbnail
這一節談的是用物件導向程式設計(object-oriented programming, OOP)的方式來實作隨機漫步。
Thumbnail
這一節談的是用物件導向程式設計(object-oriented programming, OOP)的方式來實作隨機漫步。
Thumbnail
本文介紹了Python中的物件導向程式設計的重要概念,包括類別、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型和反射。每個概念都有對應的程式碼範例來說明其用法和功能。這些概念對於理解和使用Python進行物件導向程式設計至關重要。
Thumbnail
本文介紹了Python中的物件導向程式設計的重要概念,包括類別、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型和反射。每個概念都有對應的程式碼範例來說明其用法和功能。這些概念對於理解和使用Python進行物件導向程式設計至關重要。
Thumbnail
Python語法包括條件語句、迴圈、函數和變數的使用。條件語句如if、elif和else用於進行條件判斷,for和while是兩種主要的迴圈,def用於定義函數。變數可以被賦予數字或字符串,並可使用類型提示來指定變數的類型。註解可以是單行或多行,並可用於解釋函數或類的用途和作用。
Thumbnail
Python語法包括條件語句、迴圈、函數和變數的使用。條件語句如if、elif和else用於進行條件判斷,for和while是兩種主要的迴圈,def用於定義函數。變數可以被賦予數字或字符串,並可使用類型提示來指定變數的類型。註解可以是單行或多行,並可用於解釋函數或類的用途和作用。
Thumbnail
在程式中,了解資料型態是相當重要的。 為什麽? 因為許多error,常常都是因為資料型態不正確所導致的。 舉個例子,在python中: a = 1 + 2 print(a) 結果就是3 a = = "1"+"2" print(a) 結果就是12 是不是差很多? 所以今天我來介
Thumbnail
在程式中,了解資料型態是相當重要的。 為什麽? 因為許多error,常常都是因為資料型態不正確所導致的。 舉個例子,在python中: a = 1 + 2 print(a) 結果就是3 a = = "1"+"2" print(a) 結果就是12 是不是差很多? 所以今天我來介
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News