iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0

第十二天:Python 物件導向程式設計(OOP)基礎

內容概述:

今天我們將進入 Python 中的物件導向程式設計(Object-Oriented Programming, OOP)。這是一種程式設計範式,允許我們使用「物件」來封裝數據和操作,並通過類別來設計可重用的程式結構。物件導向程式設計在現代軟體開發中非常重要,透過它可以使程式更具結構性、可讀性及擴展性。


一、什麼是物件導向?

  1. 基本概念

    • 物件導向程式設計基於「物件」和「類別」。
      • 類別(Class) 是一種設計圖,定義了物件的屬性和行為。
      • 物件(Object) 是類別的實例化結果,代表具體的實體。
    • 每個物件包含屬性(attributes)和方法(methods)。屬性是物件的狀態,方法是物件的行為。
  2. OOP 的主要特性

    • 封裝(Encapsulation):將資料和行為封裝在一起,透過物件的接口對外提供操作。
    • 繼承(Inheritance):允許新類別從現有類別繼承屬性和行為,實現重用。
    • 多型(Polymorphism):不同類別可以實現相同的方法,並表現不同的行為。
    • 抽象(Abstraction):將物件的細節隱藏,僅保留必要的接口。

二、定義類別與物件

  1. 如何定義一個類別

    • 使用 class 關鍵字來定義類別:
      class Dog:
          def __init__(self, name, age):
              self.name = name  # 定義屬性
              self.age = age
      
          def bark(self):
              print(f"{self.name} is barking.")  # 定義方法
      
  2. 創建物件

    • 要創建物件,可以將類別實例化:
      my_dog = Dog("Buddy", 5)  # 創建一個 Dog 類別的物件
      print(my_dog.name)        # 訪問物件屬性
      my_dog.bark()             # 調用物件的方法
      

三、類別的構造方法 __init__

  1. 構造方法介紹

    • __init__ 是類別的構造方法,用於在創建物件時初始化屬性:
      class Car:
          def __init__(self, brand, model, year):
              self.brand = brand
              self.model = model
              self.year = year
      
          def description(self):
              return f"{self.year} {self.brand} {self.model}"
      
  2. 實例化與使用屬性

    • 創建 Car 類別的物件並訪問屬性:
      my_car = Car("Toyota", "Corolla", 2020)
      print(my_car.description())  # 2020 Toyota Corolla
      

四、方法與屬性

  1. 實例方法

    • 實例方法是定義在類別內部,且需要物件來呼叫的函式。這些方法會操作物件的屬性:
      class Person:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
          def greet(self):
              print(f"Hello, my name is {self.name} and I am {self.age} years old.")
      
  2. 類別屬性與實例屬性

    • 類別屬性是在類別級別定義的屬性,所有實例共享;實例屬性則是每個物件各自擁有的:
      class Employee:
          company = "TechCorp"  # 類別屬性
      
          def __init__(self, name):
              self.name = name  # 實例屬性
      
  3. 改變屬性

    • 可以在物件創建後修改其屬性:
      employee = Employee("Alice")
      employee.name = "Bob"  # 修改實例屬性
      

五、繼承與多型

  1. 繼承:重用現有類別

    • 新的類別可以繼承現有的類別,獲得其屬性與方法:
      class Animal:
          def __init__(self, name):
              self.name = name
      
          def sound(self):
              pass
      
      class Dog(Animal):
          def sound(self):
              return "Woof"
      
      class Cat(Animal):
          def sound(self):
              return "Meow"
      
  2. 多型:實現相同方法的不同行為

    • 不同的類別可以有相同名稱的方法,但行為不同:
      animals = [Dog("Buddy"), Cat("Whiskers")]
      
      for animal in animals:
          print(f"{animal.name} says {animal.sound()}")
      

六、物件導向設計的應用場景

  1. 遊戲開發

    • 物件導向非常適合模擬遊戲中的角色與場景。每個角色或物件可以是具體的實體,並具有各自的屬性與行為。
  2. 數據模型

    • 物件導向可以幫助我們封裝業務邏輯和數據。例如在網頁開發中,每個使用者可以是一個物件,包含名稱、年齡、電子郵件等資訊。
  3. 軟體設計模式

    • 許多設計模式(如單例模式、工廠模式等)基於物件導向的思想,可以提升程式的擴展性和可維護性。

七、實作範例

  1. 範例 1:動物類別繼承與多型

    • 撰寫一個基礎類別 Animal,並從中派生出不同的動物類別(如 DogCat)。讓每個動物類別都有自己特有的聲音方法,並創建一些動物物件來呼叫這些方法。

      class Animal:
          def __init__(self, name):
              self.name = name
      
          def sound(self):
              pass
      
      class Dog(Animal):
          def sound(self):
              return "Woof"
      
      class Cat(Animal):
          def sound(self):
              return "Meow"
      
      # 創建物件
      dog = Dog("Buddy")
      cat = Cat("Whiskers")
      
      # 調用方法
      print(f"{dog.name} says {dog.sound()}")
      print(f"{cat.name} says {cat.sound()}")
      
  2. 範例 2:簡易銀行系統

    • 設計一個簡單的銀行系統,包含帳戶類別 Account,實現存款、取款、查詢餘額等功能:
      class Account:
          def __init__(self, owner, balance=0):
              self.owner = owner
              self.balance = balance
      
          def deposit(self, amount):
              self.balance += amount
              return f"{amount} deposited. New balance: {self.balance}"
      
          def withdraw(self, amount):
              if amount > self.balance:
                  return "Insufficient funds"
              self.balance -= amount
              return f"{amount} withdrawn. New balance: {self.balance}"
      
          def get_balance(self):
              return f"Account owner: {self.owner}, Balance: {self.balance}"
      
      # 創建帳戶
      acc = Account("Alice", 1000)
      
      # 存款與取款操作
      print(acc.deposit(500))
      print(acc.withdraw(200))
      print(acc.get_balance())
      

八、練習與實作

練習 1:類別與物件
  • 創建一個類別 Student,包含學生的姓名和成績。撰寫方法來輸出學生的基本資料和計算平均成績。
練習 2:多型練習
  • 設計一個程式,讓不同的動物類別實現相同的 speak() 方法,並根據不同的動物輸出不同的叫聲。
練習 3:銀行系統擴展
  • 基於上面的銀行系統範例,為帳戶添加功能,允許不同帳戶之間轉帳。

解答

練習 1:類別與物件

目標:創建一個 Student 類別,並包含學生的姓名和成績。撰寫方法來輸出學生的基本資料和計算平均成績。

class Student:
    def __init__(self, name, grades):
        self.name = name
        self.grades = grades  # 成績列表
    
    def display_info(self):
        print(f"學生姓名: {self.name}")
        print(f"成績: {self.grades}")
    
    def calculate_average(self):
        if len(self.grades) > 0:
            return sum(self.grades) / len(self.grades)
        else:
            return 0

# 測試程式
student1 = Student("張三", [90, 85, 88, 92])
student1.display_info()
print(f"平均成績: {student1.calculate_average():.2f}")
解釋:
  • __init__:初始化方法,用來在創建物件時設定學生的姓名和成績。
  • display_info:輸出學生的基本資料。
  • calculate_average:計算並返回學生成績的平均值。

練習 2:多型練習

目標:設計一個程式,讓不同的動物類別實現相同的 speak() 方法,並根據不同的動物輸出不同的叫聲。

class Animal:
    def speak(self):
        raise NotImplementedError("子類別必須實作這個方法")

class Dog(Animal):
    def speak(self):
        return "汪汪!"

class Cat(Animal):
    def speak(self):
        return "喵喵!"

class Cow(Animal):
    def speak(self):
        return "哞哞!"

# 測試程式
animals = [Dog(), Cat(), Cow()]

for animal in animals:
    print(f"{animal.__class__.__name__} 叫聲: {animal.speak()}")
解釋:
  • 多型(Polymorphism):不同的動物類別都繼承了 Animal 類別並實現了 speak() 方法,根據不同的動物實現各自的叫聲。
  • __class__.__name__:用來取得物件的類別名稱,便於顯示是什麼動物。

練習 3:銀行系統擴展

目標:基於先前的銀行系統,為帳戶添加轉帳功能,使不同帳戶之間能夠進行轉帳。

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance
    
    def deposit(self, amount):
        if amount > 0:
            self.balance += amount
            print(f"{self.owner} 存入 {amount} 元,餘額為 {self.balance} 元")
        else:
            print("存入金額無效。")

    def withdraw(self, amount):
        if 0 < amount <= self.balance:
            self.balance -= amount
            print(f"{self.owner} 提取 {amount} 元,餘額為 {self.balance} 元")
        else:
            print("餘額不足或無效的取款金額。")
    
    def transfer(self, recipient, amount):
        if self.balance >= amount > 0:
            self.balance -= amount
            recipient.balance += amount
            print(f"{self.owner} 向 {recipient.owner} 轉帳 {amount} 元")
            print(f"{self.owner} 餘額: {self.balance} 元")
            print(f"{recipient.owner} 餘額: {recipient.balance} 元")
        else:
            print("轉帳失敗,餘額不足或無效金額。")

# 測試程式
account1 = BankAccount("張三", 1000)
account2 = BankAccount("李四", 500)

account1.transfer(account2, 300)
解釋:
  • transfer:這是新增的轉帳功能,允許將指定金額從一個帳戶轉移到另一個帳戶。該功能首先會檢查轉帳者是否有足夠的餘額,然後才進行轉帳。

九、學習總結

物件導向程式設計是軟體開發中的一個核心概念,透過類別和物件,我們可以將程式模組化、結構化,使其更具維護性和可擴展性。在學習物件導向時,理解類別、物件、屬性、方法以及 OOP 的四大特性(封裝、繼承、多型、抽象)非常重要。希望今天的課程能夠幫助大家打下堅實的基礎,讓未來的專案開發更加順利。


下一堂課預告

第十三天:進階 Python:錯誤處理與例外管理


上一篇
從 0 開始學!跟著 ChatGPT 學會 Python 中的文件讀寫操作
下一篇
從 0 開始學!跟著 ChatGPT 學會 Python 錯誤處理
系列文
如果讓chatgpt參加iThome鐵人賽,他竟然寫出...!?31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言