พื้นฐาน Python

การเขียนโปรแกรมเชิงวัตถุใน Python

OOP จัดโปรแกรมรอบออบเจ็กต์ที่มีสถานะและเปิดเผยพฤติกรรมผ่านอินเทอร์เฟซที่ชัดเจน

การเขียนโปรแกรมเชิงวัตถุใน Python คืออะไร?

OOP สร้างแบบจำลองระบบเป็นออบเจ็กต์ที่ทำงานร่วมกัน แต่ละออบเจ็กต์รวมสถานะและการทำงานที่อนุญาต ทำให้ความรับผิดชอบในโปรแกรมใหญ่ชัดเจน

หลักสำคัญสี่ข้อของ OOP

  • Encapsulation: รวมสถานะและพฤติกรรมและควบคุมการเข้าถึง
  • Abstraction: แสดงอินเทอร์เฟซที่จำเป็นและซ่อนรายละเอียด
  • Inheritance: สร้างคลาสเฉพาะเมื่อมีความสัมพันธ์ is-a จริง
  • Polymorphism: ใช้การทำงานเดียวกันกับหลายชนิดโดยแต่ละชนิดมีพฤติกรรมเหมาะสม

การออกแบบตัวอย่าง

  1. BankAccount เป็นเจ้าของยอดเงินและตรวจสอบการฝาก
  2. SavingsAccount ใช้สัญญาของคลาสฐาน
  3. SavingsAccount override month_end เพื่อเพิ่มดอกเบี้ย
  4. ลูปจัดการทุกบัญชีผ่านอินเทอร์เฟซเดียวกัน
คำแนะนำ: ใช้ composition เมื่อออบเจ็กต์เพียงใช้อีกออบเจ็กต์ และใช้ inheritance เมื่อคลาสลูกแทนคลาสแม่ได้อย่างถูกต้อง

ตัวอย่างพื้นฐาน

รันโค้ด →
main.py
class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self._balance = float(balance)

    @property
    def balance(self):
        return self._balance

    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("Deposit must be positive")
        self._balance += amount

    def month_end(self):
        return "No interest"


class SavingsAccount(BankAccount):
    def __init__(self, owner, balance, interest_rate):
        super().__init__(owner, balance)
        self.interest_rate = interest_rate

    def month_end(self):
        self._balance *= 1 + self.interest_rate
        return "Interest applied"


accounts = [
    BankAccount("Ada", 100),
    SavingsAccount("Lin", 200, 0.05),
]
accounts[0].deposit(50)

for account in accounts:
    status = account.month_end()
    print(f"{account.owner}: {account.balance:.2f} ({status})")

ผลลัพธ์ที่คาดหวัง

Ada: 150.00 (No interest)
Lin: 210.00 (Interest applied)

หลัก OOP ทั้งสี่ในการใช้งานจริง

ตัวอย่างเหล่านี้แสดงวิธีที่ Python ใช้ encapsulation, abstraction, inheritance และ polymorphism ในโค้ดทั่วไป

Encapsulation

รันโค้ด →

รวมสถานะและพฤติกรรมและควบคุมการเข้าถึง

encapsulation.py
class BankAccount:
    def __init__(self, balance=0):
        # Double underscores prevent accidental direct access.
        self.__balance = balance

    @property
    def balance(self):
        # Expose read access without exposing mutation.
        return self.__balance

    def deposit(self, amount):
        # Keep validation next to the state it protects.
        if amount <= 0:
            raise ValueError("Amount must be positive")
        self.__balance += amount


account = BankAccount(100)
account.deposit(50)
print(account.balance)  # 150

Abstraction

รันโค้ด →

แสดงอินเทอร์เฟซที่จำเป็นและซ่อนรายละเอียด

abstraction.py
from abc import ABC, abstractmethod


class PaymentMethod(ABC):
    @abstractmethod
    def pay(self, amount):
        # Callers know what pay does, not how each provider does it.
        pass


class CreditCard(PaymentMethod):
    def pay(self, amount):
        # The concrete class hides its payment implementation.
        return f"Paid ${amount:.2f} by card"


payment = CreditCard()
print(payment.pay(25))

Inheritance

รันโค้ด →

สร้างคลาสเฉพาะเมื่อมีความสัมพันธ์ is-a จริง

inheritance.py
class Employee:
    def __init__(self, name):
        self.name = name

    def describe(self):
        return self.name


class Developer(Employee):
    def __init__(self, name, language):
        # Reuse initialization from the parent class.
        super().__init__(name)
        self.language = language

    def describe(self):
        # Extend inherited behavior instead of duplicating it.
        return f"{super().describe()} writes {self.language}"


print(Developer("Ada", "Python").describe())

Polymorphism

รันโค้ด →

ใช้การทำงานเดียวกันกับหลายชนิดโดยแต่ละชนิดมีพฤติกรรมเหมาะสม

polymorphism.py
class EmailNotification:
    def send(self, message):
        return f"Email: {message}"


class SmsNotification:
    def send(self, message):
        return f"SMS: {message}"


def notify(channels, message):
    for channel in channels:
        # The same call selects behavior from each concrete object.
        print(channel.send(message))


channels = [EmailNotification(), SmsNotification()]
notify(channels, "Order shipped")

หลักการทำงาน

BankAccount ห่อหุ้มยอดเงิน SavingsAccount สืบทอดอินเทอร์เฟซและ override month_end ลูปใช้ออบเจ็กต์ทั้งสองแบบเดียวกันและ Python เลือกเมธอดขณะรัน

เปลี่ยนค่าและรันโปรแกรมด้วย คอมไพเลอร์ Python ออนไลน์ของ CodeUtility โดยไม่ต้องติดตั้ง Python

แบบฝึกหัด

ลองเปลี่ยน input และทดสอบกรณีขอบก่อนใช้ชุดข้อมูลที่ใหญ่ขึ้น

  1. คาดเดา output ก่อนรัน
  2. รองรับ input ว่างหรือไม่ถูกต้อง
  3. แยก logic เป็นฟังก์ชันและเพิ่ม test case
รันใน Python IDE →