Introduction to Python Applications 2025 - Selenium === ###### tags: `Python` `Python and Its Application 2025` ## `class` `class` 是 Python 用來定義\*\*類別(Class)\*\*的關鍵字。類別是物件導向程式設計(OOP, Object-Oriented Programming)的核心,用來建立自訂的資料型態(object = 類別的實體)。 ### 建立一個類別與物件 ```python class Dog: def __init__(self, name, age): self.name = name # 屬性 self.age = age # 屬性 def bark(self): # 方法 print(f"{self.name} says: Woof!") ``` * `__init__` 是建構子(constructor),當你建立物件時會自動呼叫。 * `self` 是代表「自己的物件實體」,類似 Java 裡的 `this`。 #### 建立物件(實體) ```python dog1 = Dog("Buddy", 3) dog1.bark() # Buddy says: Woof! ``` ### 類別的屬性與方法 * **屬性(Attribute)**:類別中儲存的資料,例如 `self.name` * **方法(Method)**:類別中的函式,例如 `bark()` ```python print(dog1.name) # Buddy dog1.age = 4 print(dog1.age) # 4 ``` ## 類別與繼承(Inheritance) ```python class Animal: def speak(self): print("Animal speaks") class Cat(Animal): def speak(self): print("Meow") cat1 = Cat() cat1.speak() # Meow(會覆蓋父類別的方法) ``` ### 什麼是繼承(Inheritance)? 繼承讓你可以建立一個**新的類別**,它**沿用現有類別的屬性和方法**,並可進行擴充或覆寫(Override)。 * **父類別 / 基底類別(Parent/Base Class)**:被繼承的類別 * **子類別 / 衍生類別(Child/Derived Class)**:繼承別人的類別 ### 基本語法 ```python class Animal: def speak(self): print("Animal makes a sound") class Dog(Animal): # Dog 繼承自 Animal def speak(self): print("Dog says: Woof") ``` ```python a = Animal() d = Dog() a.speak() # Animal makes a sound d.speak() # Dog says: Woof(覆寫了父類別的方法) ``` ### 使用 `super()` 呼叫父類別方法 在子類別中想要**延伸**父類別的方法而不是完全覆寫,可以用 `super()`。 ```python class Animal: def __init__(self, name): self.name = name def speak(self): print(f"{self.name} makes a sound") class Cat(Animal): def speak(self): super().speak() # 呼叫父類別的 speak print(f"{self.name} says: Meow") c = Cat("Kitty") c.speak() # Kitty makes a sound # Kitty says: Meow ``` ### 建構子也可以繼承 如果子類別有自己的 `__init__()`,可以用 `super().__init__()` 呼叫父類別的建構子: ```python class Animal: def __init__(self, name): self.name = name class Dog(Animal): def __init__(self, name, breed): super().__init__(name) # 呼叫父類別初始化 name self.breed = breed # 子類別自己的屬性 d = Dog("Buddy", "Labrador") print(d.name) # Buddy print(d.breed) # Labrador ``` ### 多重繼承(Multiple Inheritance) Python 允許**多個父類別**: ```python class A: def do_something(self): print("A") class B: def do_something_else(self): print("B") class C(A, B): pass c = C() c.do_something() # A c.do_something_else() # B ``` 多重繼承需要注意 **方法解析順序(MRO, Method Resolution Order)**,可用 `.mro()` 來查詢: ```python print(C.mro()) ``` ### `isinstance()` 和 `issubclass()` * `isinstance(obj, Class)`:判斷物件是否是某類別或其子類別的實例 * `issubclass(SubClass, SuperClass)`:判斷是否為子類別 ```python print(isinstance(d, Dog)) # True print(isinstance(d, Animal)) # True print(issubclass(Dog, Animal)) # True ``` ### 應用場景範例 #### 例:交通工具繼承 ```python class Vehicle: def move(self): print("Moving...") class Car(Vehicle): def move(self): print("Driving on road") class Boat(Vehicle): def move(self): print("Sailing on water") vehicles = [Car(), Boat()] for v in vehicles: v.move() ``` ### 小結 | 功能 | 說明 | | --------------------------- | ---------------------- | | `class SubClass(BaseClass)` | 建立子類別 | | `super()` | 呼叫父類別的方法或建構子 | | 覆寫方法 | 子類別重新定義父類別的方法 | | 多重繼承 | 可繼承多個類別,注意方法解析順序 (MRO) | ## 類別與內建魔術方法(Magic Methods) Python 的 **Magic Methods**(魔術方法),又叫 **dunder methods(double underscore methods)**,是 Python 內部特別命名的方法,用來定義物件的**行為**,讓你可以像操作內建型別那樣操作自訂物件。魔術方法的命名規則是: ``` __method_name__ ``` 例如: * `__init__`:建構子,物件建立時呼叫 * `__str__`:定義 `str(obj)` 或 `print(obj)` 的輸出 * `__add__`:定義 `obj1 + obj2` 的行為 ### 1. 建構與轉換類別 | 方法 | 說明 | | - | - | | `__init__` | 物件初始化(建構子) | | `__del__` | 解構子,物件刪除時執行(不常用) | | `__str__` | `str(obj)` 或 `print(obj)` 顯示的內容 | | `__repr__` | `repr(obj)`,提供開發者看的資訊 | | `__bool__` | `bool(obj)`,可定義物件在布林運算中的行為 | | `__int__`, `__float__` | 型別轉換 `int(obj)`、`float(obj)` | #### 範例: ```python class User: def __init__(self, name): self.name = name def __str__(self): return f"User: {self.name}" def __repr__(self): return f"<User name={self.name}>" u = User("Alice") print(str(u)) # User: Alice print(repr(u)) # <User name=Alice> ``` ### 2. 運算子重載(Operator Overloading) | 方法 | 對應運算子 | | -- | -- | | `__add__` | `+` | | `__sub__` | `-` | | `__mul__` | `*` | | `__truediv__` | `/` | | `__floordiv__` | `//` | | `__mod__` | `%` | | `__pow__` | `**` | | `__eq__` | `==` | | `__ne__` | `!=` | | `__lt__` | `<` | | `__le__` | `<=` | | `__gt__` | `>` | | `__ge__` | `>=` | #### 範例: ```python class Point: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): return Point(self.x + other.x, self.y + other.y) def __eq__(self, other): return self.x == other.x and self.y == other.y def __str__(self): return f"({self.x}, {self.y})" p1 = Point(1, 2) p2 = Point(3, 4) print(p1 + p2) # (4, 6) print(p1 == p2) # False ``` ### 3. 容器行為(模擬 list、dict 等) | 方法 | 說明 | | -- | - | | `__len__` | 定義 `len(obj)` | | `__getitem__` | `obj[key]` | | `__setitem__` | `obj[key] = val` | | `__delitem__` | `del obj[key]` | | `__contains__` | `in` 運算子 | | `__iter__` | 可迭代(for 迴圈用) | | `__next__` | 搭配 `__iter__`,產生下一項 | #### 範例: ```python class MyList: def __init__(self): self.data = [] def __getitem__(self, index): return self.data[index] def __setitem__(self, index, value): self.data[index] = value def __len__(self): return len(self.data) def add(self, value): self.data.append(value) ml = MyList() ml.add(10) ml.add(20) print(ml[1]) # 20 ml[0] = 99 print(ml[0]) # 99 print(len(ml)) # 2 ``` ### 4. 其他有趣的方法 | 方法 | 說明 | | ----- | --- | | `__call__` | 讓物件像函式一樣被呼叫 | | `__enter__` / `__exit__` | 支援 `with` 語法(Context Manager) | | `__copy__` / `__deepcopy__` | 控制 `copy` 模組的行為 | | `__hash__` | 定義物件是否可做為 `set` 或 `dict` 的 key | | `__getattr__` / `__setattr__` | 動態取得/設定屬性(較進階) | #### `__call__` 範例: ```python class Greeter: def __init__(self, name): self.name = name def __call__(self): print(f"Hello, {self.name}!") g = Greeter("Bob") g() # Hello, Bob! ``` ### 小結:為什麼要用 Magic Methods? * 模擬內建型別(如 `list`、`dict`、`str`)的行為 * 提升物件的可讀性與可操作性 * 讓自訂類別支援 Python 語法糖(例如 `+`、`in`、`len()`、`with`) ## 類別變數 vs 實例變數 ```python class Counter: count = 0 # 類別變數(所有實例共用) def __init__(self): Counter.count += 1 # 每建立一個物件就加 1 print(Counter.count) # 0 a = Counter() b = Counter() print(Counter.count) # 2 ``` ## 私有屬性與方法(封裝) * 在 Python 中,用 `_` 或 `__` 開頭代表私有(非強制性) ```python class BankAccount: def __init__(self, balance): self.__balance = balance # 私有變數 def deposit(self, amount): self.__balance += amount def get_balance(self): return self.__balance acct = BankAccount(1000) acct.deposit(500) print(acct.get_balance()) # 1500 # print(acct.__balance) # 錯誤:無法直接存取 ```