首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Python 判斷變數是否已定義:正規寫法與 PHP isset 對照

     編輯:PHP 相關知識

核心結論:Python 沒有 isset(),請用 try/except NameError 或 in 檢查命名空間

常見場景與正規寫法

1. 檢查區域/全域變數是否存在

# ❌ 錯誤:直接引用未定義變數會拋出 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

2. 檢查字典鍵是否存在(最常見需求)

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}")

3. 檢查物件屬性是否存在

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", "無電話"))  # 無電話

4. 檢查模組層級變數/常數

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 寫法存在嚴重問題:

  1. 安全性:eval() 會執行任意程式碼,若 v 來自使用者輸入,極易導致程式碼注入。
  2. 語義錯誤:eval("var") 會嘗試取值而非檢查存在性;若變數存在但值為 0、""、[] 等 falsy 值,會誤判為「未定義」。
  3. 效能:eval() 需編譯字串,比字典查找慢數個數量級。
  4. 作用域混亂:eval() 預設在當前區域/全域命名空間,難以精確控制檢查範圍。

PHP 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()。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved