isset(),請用 try/except NameError 或 in 檢查命名空間# ❌ 錯誤:直接引用未定義變數會拋出 NameError
# print(user_name)
# ✅ 正確:使用 try/except 捕捉 NameError
try:
print(user_name)
except NameError:
print("user_name 未定義")
# ✅ 進階:封裝成可重用函數(模擬 PHP isset 行為)
def is_defined(var_name: str, frame=None) -> bool:
"""
檢查變數名稱是否在指定框架的區域或全域命名空間中存在。
:param var_name: 變數名稱字串
:param frame: stack frame,預設為呼叫者的框架
:return: True/False
"""
import sys
if frame is None:
frame = sys._getframe(1)
return var_name in frame.f_locals or var_name in frame.f_globals
# 使用範例
user_name = "Alice"
print(is_defined("user_name")) # True
print(is_defined("age")) # False
data = {"name": "Bob"}
# ✅ 推薦:in 運算子
if "name" in data:
print(data["name"])
# ✅ 取值並提供預設值:dict.get()
print(data.get("age", "未提供")) # 未提供
# ✅ Python 3.8+:walrus operator 結合 get
if (age := data.get("age")) is not None:
print(f"年齡:{age}")
class User:
def __init__(self, name):
self.name = name
user = User("Charlie")
# ✅ hasattr() - 檢查實例屬性或類別屬性
if hasattr(user, "email"):
print(user.email)
# ✅ getattr() - 取值並給預設值
print(getattr(user, "phone", "無電話")) # 無電話
import myconfig
# ✅ 使用 hasattr 模組物件
if hasattr(myconfig, "DEBUG"):
print("DEBUG 模式:", myconfig.DEBUG)
# ✅ 或直接用 try/except
try:
print(myconfig.API_KEY)
except AttributeError:
print("API_KEY 未設定")
eval() 模擬 isset()?原文提供的 def isset(v): return 1 if eval(v) else 0 寫法存在嚴重問題:
eval() 會執行任意程式碼,若 v 來自使用者輸入,極易導致程式碼注入。eval("var") 會嘗試取值而非檢查存在性;若變數存在但值為 0、""、[] 等 falsy 值,會誤判為「未定義」。eval() 需編譯字串,比字典查找慢數個數量級。eval() 預設在當前區域/全域命名空間,難以精確控制檢查範圍。isset() vs Python 機制對照表| PHP 行為 | Python 對應寫法 | 備註 |
|---|---|---|
isset($var) 變數存在且非 null | "var" in locals() or "var" in globals() | Python 變數無「null」概念,None 是合法值 |
isset($arr['key']) | 'key' in arr | 字典鍵存在性 |
isset($obj->prop) | hasattr(obj, 'prop') | 屬性存在性 |
isset($var) && $var 存在且 truthy | 'var' in locals() and locals()['var'] | 需分兩步驟 |
name = None),後續直接用 if name is not None 判斷,避免「未定義」狀態。mypy、pyright 可在編譯期發現未定義變數。in/get() 檢查能力。eval()/exec():動態變數名稱是設計缺陷,改用字典鍵值對。Python 的命名空間機制(區域、全域、內建)清晰且一致,「檢查變數是否定義」實際上是「檢查名稱是否在命名空間字典中」。掌握 in、hasattr()、getattr()、try/except NameError 四大工具,即可優雅解決所有檢查需求,無需模擬 PHP 的 isset()。