在 Python 中,生成器與裝飾器是兩個非常強大的特性,分別讓我們能更高效地處理數據流和更靈活地擴展函數的功能。本篇文章將詳細介紹:
yield
的概念與應用yield
生成器(Generator)是一種特殊的迭代器,允許我們在處理大型數據集時,按需生成數據,而不是一次性將所有數據存儲在記憶體中。這不僅節省了內存,還提升了效率。
生成器是通過函數與 yield
關鍵字實現的,並不像普通函數那樣直接返回結果,而是生成一個「可迭代的對象」。
yield
定義生成器yield
是生成器的核心。每次執行到 yield
時,函數會暫停執行並返回一個值,直到再次被調用時從暫停的位置繼續執行。
def simple_generator():
yield 1
yield 2
yield 3
# 使用生成器
gen = simple_generator()
print(next(gen)) # Output: 1
print(next(gen)) # Output: 2
print(next(gen)) # Output: 3
def even_numbers(n):
for i in range(n):
if i % 2 == 0:
yield i
# 使用生成器
for num in even_numbers(10):
print(num, end=" ") # Output: 0 2 4 6 8
生成器的優點:
裝飾器(Decorator)是 Python 中的一種設計模式,它允許我們在不改變原始函數的情況下,動態地為其增加功能。裝飾器本質上是一個接收函數作為參數的高階函數。
def my_decorator(func):
def wrapper():
print("這是在函數執行前添加的代碼")
func()
print("這是在函數執行後添加的代碼")
return wrapper
@my_decorator
def say_hello():
print("Hello, World!")
say_hello()
執行結果:
這是在函數執行前添加的代碼
Hello, World!
這是在函數執行後添加的代碼
def say_hello():
print("Hello, World!")
decorated_function = my_decorator(say_hello)
decorated_function()
函數執行計時器
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 執行時間: {end_time - start_time:.4f} 秒")
return result
return wrapper
@timer
def slow_function():
time.sleep(2)
print("函數執行完畢")
slow_function()
權限檢查
def require_login(func):
def wrapper(user, *args, **kwargs):
if not user.get("is_logged_in"):
print("用戶未登入,無法執行此操作")
return
return func(user, *args, **kwargs)
return wrapper
@require_login
def view_profile(user):
print(f"查看用戶 {user['name']} 的資料")
# 測試
user1 = {"name": "Alice", "is_logged_in": True}
user2 = {"name": "Bob", "is_logged_in": False}
view_profile(user1) # 正常執行
view_profile(user2) # 提示未登入
記錄日誌
def log(func):
def wrapper(*args, **kwargs):
print(f"函數 {func.__name__} 被呼叫,參數為: {args}, {kwargs}")
return func(*args, **kwargs)
return wrapper
@log
def add(x, y):
return x + y
print(add(3, 5)) # Output: 8
Python 的生成器與裝飾器極大提升了程式設計的靈活性與表達能力。掌握這兩個特性,將能更高效地解決複雜問題,並撰寫出簡潔、優雅的程式碼。
fibonacci(n)
,生成前 n
個 Fibonacci 數。capitalize_return
,將原函數的返回值(字串)轉為大寫。有任何問題或需要更深入的例子,歡迎在評論區留言!