本文整理 Python 函數與類的核心知識點,針對**參數傳遞機制、作用域規則、裝飾器本質、類方法靜態方法、繼承 MRO、數據模型協議**進行系統筆記,適合 Java/Go 開發者快速遷移、面試複習或項目查漏補缺。
def func(pos_only, /, pos_or_kw, *, kw_only, **kwargs):
pass
# 1. 位置-only (Python 3.8+ / 分隔符)
# 2. 位置或關鍵字 (預設)
# 3. *args 收集剩餘位置參數 → tuple
# 4. 關鍵字-only (* 後或 *args 後)
# 5. **kwargs 收集剩餘關鍵字參數 → dict
append) 影響外部;**重新賦值參數變量**不影響外部。
def modify(lst, num):
lst.append(99) # 影響外部
num = 100 # 不影響外部
lst = [1,2,3] # 不影響外部 (重新綁定局部變量)
a = [1,2]; b = 10
modify(a, b)
print(a, b) # [1, 2, 99] 10
def bad_append(val, lst=[]): # 危險!
lst.append(val)
return lst
print(bad_append(1)) # [1]
print(bad_append(2)) # [1, 2] ← 共享同一列表!
def good_append(val, lst=None):
if lst is None: lst = []
lst.append(val)
return lst
def demo(a, b, *args, kw1, kw2, **kwargs):
print(a, b, args, kw1, kw2, kwargs)
demo(1, 2, 3, 4, kw1=5, kw2=6, kw3=7, kw4=8)
# 1 2 (3, 4) 5 6 {'kw3': 7, 'kw4': 8}
# 解包調用
tup = (10, 20)
dct = {'kw1': 30, 'kw2': 40, 'kw3': 50}
demo(*tup, **dct) # 10 20 () 30 40 {'kw3': 50}
x = 100 # Global (模塊級)
def outer():
x = 200 # Enclosing
def inner():
nonlocal x # 修改 Enclosing 層 x
x = 300
print("inner:", x) # 300
inner()
print("outer:", x) # 300 (被修改)
outer()
print("global:", x) # 100 (未被修改)
| 作用域 | 關鍵字 | 可讀 | 可寫 (需聲明) |
|--------|--------|------|---------------|
| Local (函數內) | - | ✅ | ✅ |
| Enclosing (外層函數) | `nonlocal` | ✅ | ✅ |
| Global (模塊級) | `global` | ✅ | ✅ |
| Builtins (內建) | - | ✅ | ❌ |
import functools
def timer(func):
@functools.wraps(func) # 保留 __name__, __doc__, __annotations__
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.perf_counter()-start:.4f}s")
return result
return wrapper
@timer
def slow_add(a, b):
time.sleep(0.1)
return a + b
def repeat(times):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello {name}")
class CountCalls:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"Call {self.count} to {self.func.__name__}")
return self.func(*args, **kwargs)
@CountCalls
def add(a, b): return a + b
class Demo:
def instance_method(self): # 實例方法:隱式傳 self
return self
@classmethod
def class_method(cls): # 類方法:隱式傳 cls,可被繼承覆寫
return cls
@staticmethod
def static_method(): # 靜態方法:無隱式傳遞,工具函數歸屬類命名空間
return "static"
# 調用
Demo.instance_method(Demo()) # 手動傳 self
Demo.class_method() # 自動傳 Demo
Demo.static_method() # 直接調用
class Celsius:
def __init__(self, temp=0):
self._temp = temp
@property
def temperature(self):
return self._temp
@temperature.setter
def temperature(self, value):
if value < -273.15: raise ValueError("Below absolute zero")
self._temp = value
@temperature.deleter
def temperature(self):
del self._temp
class A:
def __init__(self):
self.public = 1
self._protected = 2 # 約定俗成:內部使用
self.__private = 3 # 名稱修飾 → _A__private
a = A()
print(a._A__private) # 3 (可訪問,但不建議)
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
print(D.__mro__)
# (D, B, C, A, object) ← C3 線性化算法:深度優先、左優先、單調性
| 協議 | 方法 | 用途 |
|---|---|---|
| 構造/初始化 | `__new__`, `__init__` | 實例創建、初始化 |
| 字串表示 | `__str__`, `__repr__` | `print()` vs 除錯 |
| 比較 | `__eq__`, `__lt__`... | `==`, `<`, `sorted()` |
| 容器 | `__len__`, `__getitem__`, `__setitem__`, `__iter__` | `len()`, `[]`, `in`, `for` |
| 可呼叫 | `__call__` | `obj()` |
| 上下文管理 | `__enter__`, `__exit__` | `with obj:` |
| 屬性訪問 | `__getattr__`, `__setattr__`, `__getattribute__` | 動態屬性、代理 |
| 序列化 | `__reduce__`, `__getstate__`, `__setstate__` | `pickle` |
class Base: pass
class Left(Base): pass
class Right(Base): pass
class Diamond(Left, Right): pass
# MRO: Diamond → Left → Right → Base → object
# super() 按 MRO 鏈調用,保證每個類只初始化一次
is 比較身份 (id/記憶體地址);== 比較值 (調用 __eq__)。[] is [] → False, [] == [] → True。💡 Pythonic 原則:顯式優於隱式、簡單優於複雜、可讀性至上。善用 `with`、列表推導式、生成器、上下文管理器、類型提示 (PEP 484) 寫出健壯、可維護的代碼。