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) # 錯誤:無法直接存取
```