Python判斷是不是數字:精準辨識的各種方法與深度解析

Python 判斷數字的終極指南

嘿,各位 Python 愛好者!有沒有遇過這種情況:你從使用者那裡收到一串字串,或者從檔案讀取了一批資料,然後就開始頭痛,「這到底是不是數字啊?」。相信我,這絕對是開發過程中一個非常常見,但又得處理得漂漂亮亮的問題!尤其是在做資料處理、輸入驗證,或是數學運算的相關程式碼時,如果不能精準判斷,那可是會引發一連串難以預料的錯誤,真的會讓人槌心肝!

別擔心!今天,我就要帶著大家一起深入探討「Python 判斷是不是數字」這個主題,從最基礎的方法到一些進階的技巧,我會用最貼近實際開發的經驗,把每一個細節都講清楚,講明白,讓你以後面對這類問題,都能游刃有餘,輕鬆搞定!我們不只會看到「怎麼做」,更會了解「為什麼這麼做」,以及在不同情境下,哪種方法是你的最佳選擇。

為什麼判斷數字如此重要?

在我們深入探討各種方法之前,先來聊聊,為什麼這件事情這麼重要,對吧?

  • 資料輸入驗證: 當使用者輸入資料時(例如註冊帳號的手機號碼、訂單的數量),你絕對不希望他們輸入一堆字母或符號進來。精確的數字判斷,能確保資料的正確性,避免後續處理的麻煩。
  • 數學運算: Python 的數學運算符號(如 `+`, `-`, `*`, `/`)只能作用於數字型別。如果你試圖對字串執行加法,可能會得到字串拼接的結果,而非數學上的加總,這絕對不是你想要的!
  • 資料清洗與轉換: 在處理從外部來源(如 CSV 檔、API 請求)獲取的資料時,數字常常會以字串的形式出現。你需要將它們轉換成真正的數字型別(整數 `int` 或浮點數 `float`)才能進行分析或計算。
  • 邏輯判斷: 許多程式邏輯是建立在數字比較上的(例如,「如果分數大於 90 就給 A」)。準確的數字判斷是這些邏輯能正確運作的基石。

總之,這可不是一件小事!處理不好,輕則程式出錯,重則可能導致資料損壞,影響整個應用程式的穩定性。所以,掌握這些判斷技巧,絕對是每個 Python 開發者必備的技能。

方法一:利用 `isdigit()` 和 `isnumeric()` 方法

首先,我們來認識兩個字串物件內建的方法:`isdigit()` 和 `isnumeric()`。這兩個方法聽起來很直觀,對吧?它們主要用於判斷一個字串是否只包含數字字元

`isdigit()` 的秘密

`isdigit()` 方法會回傳 `True`,如果字串中的所有字元都是數字(0-9),並且至少有一個字元。反之,則回傳 `False`。它不支援負號、小數點或指數符號。

讓我們看看幾個例子,這樣會更清楚:

print("12345".isdigit())     # 輸出: True
print("123.45".isdigit())    # 輸出: False (因為有小數點)
print("-123".isdigit())     # 輸出: False (因為有負號)
print("123a".isdigit())     # 輸出: False (因為有字母 'a')
print("".isdigit())        # 輸出: False (因為是空字串)

可以看到,`isdigit()` 的判斷條件其實相當嚴格,它只認可我們一般意義上的「阿拉伯數字」。

`isnumeric()` 的異同

`isnumeric()` 方法的行為與 `isdigit()` 類似,但它更廣泛一些。除了 0-9 的數字之外,它還能辨識一些 Unicode 中的數字字元,例如中文數字、羅馬數字中的一部分,還有分數、上標、下標等。不過,它同樣不支援負號或小數點。

舉個例子:

print("12345".isnumeric())    # 輸出: True
print("一二三".isnumeric())  # 輸出: True (這是中文數字)
print("²".isnumeric())      # 輸出: True (這是上標數字)
print("⅓".isnumeric())      # 輸出: True (這是分數)
print("123.45".isnumeric())   # 輸出: False (小數點)
print("-123".isnumeric())    # 輸出: False (負號)

哇,是不是有點意思?`isnumeric()` 在處理包含不同語言或特殊數字符號的資料時,會比 `isdigit()` 更方便一些。

方法二:使用 `try-except` 區塊進行型別轉換

上面介紹的 `isdigit()` 和 `isnumeric()` 雖然好用,但它們有個很大的局限:它們只能判斷字串看起來像數字,卻無法直接告訴你,這個字串能不能被 Python實際轉換成數字型別(`int` 或 `float`)。

例如,我們想要判斷 `”123.45″` 這串字串能不能被轉換成浮點數。`isdigit()` 和 `isnumeric()` 都會回傳 `False`,但實際上,`float(“123.45”)` 是可以成功的!

這時候,最強大的方法就登場了:利用 `try-except` 區塊來嘗試進行型別轉換! 這絕對是我在實際開發中最常用,也最推薦的方法,尤其是在你需要判斷一個字串是否能轉換為 `int` 或 `float` 時。它的邏輯很簡單:

  1. 嘗試 (try): 試著將這個字串轉換成你想要的數字型別(例如 `int()` 或 `float()`)。
  2. 如果成功: 那麼它就是一個有效的數字。
  3. 如果失敗 (except): 如果在轉換過程中出現了 `ValueError`(值錯誤),那就代表這個字串無法被轉換成數字,也就是說,它不是一個有效的數字。

這個方法非常優雅,而且能處理各種情況,包括:

  • 整數(正負皆可):`”123″`, `”-45″`
  • 浮點數(正負皆可):`”123.45″`, `”-6.78″`, `”.5″`
  • 科學記號表示法:`”1e-3″`, `”2.5E+2″`

讓我們看看程式碼怎麼寫:

判斷是否為整數 (`int`)
def is_integer(s):
    try:
        int(s)
        return True
    except ValueError:
        return False

print(is_integer("123"))     # 輸出: True
print(is_integer("-45"))    # 輸出: True
print("123.45".is_integer()) # 輸出: False (因為 int("123.45") 會引發 ValueError)
print("abc".is_integer())    # 輸出: False
print("".is_integer())       # 輸出: False
print("1e3".is_integer())    # 輸出: False (int("1e3") 會引發 ValueError)
判斷是否為浮點數 (`float`)

這個方法就更厲害了,它能判斷一個字串是否能被轉換成一個浮點數,這包含了整數和小數。

def is_float(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

print(is_float("123"))      # 輸出: True (float("123") 可以成功)
print(is_float("-45"))     # 輸出: True
print("123.45".is_float())  # 輸出: True
print("-6.78".is_float())   # 輸出: True
print("1e-3".is_float())    # 輸出: True (科學記號也可以)
print("2.5E+2".is_float())  # 輸出: True
print("abc".is_float())     # 輸出: False
print("".is_float())        # 輸出: False
print("123,45".is_float())  # 輸出: False (逗號在 Python 中不是小數點)

我的經驗談: 在實際開發中,我通常會先判斷一個字串是否能被轉換成 `float`。如果能,那它就是一個數字。除非你的需求非常明確,必須區分整數和浮點數,否則 `is_float` 的判斷通常已經足夠應付大多數情況了。它同時也處理了 `isdigit()` 和 `isnumeric()` 無法處理的負數和小數。

方法三:使用正規表達式 (Regular Expressions)

對於更複雜的數字模式判斷,我們就得請出「正規表達式」這個強大的工具了!正規表達式(Regular Expression,簡稱 regex 或 regexp)是一種用來描述字串模式的工具,它能讓你精確地定義你想要的字串結構。

在 Python 中,我們可以使用 `re` 模組來處理正規表達式。雖然它看起來可能有點複雜,但一旦你掌握了,它就能解決很多棘手的字串匹配問題。

基本數字模式

例如,我們想判斷一個字串是否只包含數字(0-9),並且可以有一個負號在開頭:

import re

def is_digit_with_sign(s):
    # ^: 匹配字串開頭
    # -?: 可選的負號
    # \d+: 一個或多個數字
    # $: 匹配字串結尾
    pattern = r"^-?\d+$"
    if re.match(pattern, s):
        return True
    else:
        return False

print(is_digit_with_sign("123"))     # 輸出: True
print(is_digit_with_sign("-45"))    # 輸出: True
print(is_digit_with_sign("+45"))    # 輸出: False (這裡我們沒有允許 '+' 號)
print(is_digit_with_sign("123.45")) # 輸出: False
print(is_digit_with_sign("abc"))    # 輸出: False
包含浮點數的模式

要處理包含小數點和科學記號的數字,正規表達式就會變得更複雜一些。一個相對完整的浮點數模式可能看起來像這樣:

import re

def is_number_regex(s):
    # 這個正規表達式可以匹配整數、浮點數、科學記號表示法
    # 它可以包含可選的正負號
    pattern = r"^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$"
    if re.match(pattern, s):
        return True
    else:
        return False

print(is_number_regex("123"))       # 輸出: True
print(is_number_regex("-123"))      # 輸出: True
print("123.45".is_number_regex())   # 輸出: True
print("-123.45".is_number_regex())  # 輸出: True
print(".5".is_number_regex())       # 輸出: True
print("5.".is_number_regex())       # 輸出: True
print("1e-3".is_number_regex())     # 輸出: True
print("2.5E+2".is_number_regex())   # 輸出: True
print("abc".is_number_regex())      # 輸出: False
print("1,234".is_number_regex())    # 輸出: False (逗號不被視為數字分隔符)
print("".is_number_regex())         # 輸出: False

我的觀點: 正規表達式非常強大,但它的學習曲線比較陡峭。對於「Python 判斷是不是數字」這個基本任務,除非你有非常特殊的需求(例如,你希望判斷的數字格式非常明確,且不希望透過 `try-except` 來處理,或者你需要一次性匹配多種數字格式),否則我還是會優先考慮 `try-except` 的方法。因為 `try-except` 通常更簡潔、更容易理解,而且對於大多數常見的數字格式,它已經處理得相當不錯了。

方法四:檢查變數的型別 (`type()`)

有時候,你可能不是在處理字串,而是直接拿到一個變數,想知道它是不是一個數字。這時候,直接使用 Python 的 `type()` 函數就是最直接了當的方法!

`type()` 函數會回傳變數的型別物件。我們可以將它與 Python 內建的數字型別(`int`, `float`, `complex` – 複數)進行比較。

def is_actual_number(var):
    if type(var) in (int, float, complex):
        return True
    else:
        return False

num_int = 100
num_float = 100.5
num_complex = 1 + 2j
text_str = "hello"
bool_val = True

print(is_actual_number(num_int))       # 輸出: True
print(is_actual_number(num_float))     # 輸出: True
print(is_actual_number(num_complex))   # 輸出: True
print(is_actual_number(text_str))      # 輸出: False
print(is_actual_number(bool_val))      # 輸出: False (布林值在 Python 中是 int 的子類別,所以 type(True) == int,嚴格來說會是 True,但這裡我們討論的是明確的數字型別,所以這個範例可能有點小陷阱,但 `isinstance` 會更精確)

進階一點:使用 `isinstance()`

相較於直接用 `type()` 比較,`isinstance()` 函數通常是更好的選擇。`isinstance(object, classinfo)` 會檢查 `object` 是否是 `classinfo` 或其子類別的實例。這在處理繼承時非常有用。

def is_number_instance(var):
    # 檢查是否是 int, float, 或 complex 的實例
    if isinstance(var, (int, float, complex)):
        return True
    else:
        return False

print(is_number_instance(100))       # 輸出: True
print(is_number_instance(100.5))     # 輸出: True
print(is_number_instance(1 + 2j))    # 輸出: True
print(is_number_instance("hello"))   # 輸出: False
print(is_number_instance(True))      # 輸出: True (因為 bool 是 int 的子類別)
print(is_number_instance(False))     # 輸出: True

我的建議: 如果你已經確定拿到的是一個變數,而不是從外部讀取的字串,並且你想檢查它是否是 Python 的原生數字型別,那麼 `isinstance()` 是最清晰、最 Pythonic 的做法。它能正確區分 `bool` 和 `int`,儘管 `bool` 在底層繼承自 `int`。如果你只想排除 `bool`,可以這樣寫:

def is_strict_number_instance(var):
    if isinstance(var, (int, float, complex)) and not isinstance(var, bool):
        return True
    else:
        return False

print(is_strict_number_instance(True)) # 輸出: False
print(is_strict_number_instance(100))  # 輸出: True

方法五:結合 `isinstance()` 與 `try-except` 處理複合型別

在實際開發中,資料來源非常多樣。你可能會遇到一些比較特殊的數字型別,例如 NumPy 陣列中的數字(`numpy.int64`, `numpy.float64` 等),或者 Pandas Series 中的數字。

這時候,我們就需要一個更具彈性的方法,結合 `isinstance()` 和 `try-except` 來處理。這種方法通常會先檢查是否為 Python 的原生數字型別,如果不是,再嘗試用 `try-except` 轉換。

這是一個相對全面的判斷函數:

def is_any_number(var):
    # 1. 先檢查是否為 Python 原生數字型別 (排除布林值)
    if isinstance(var, (int, float, complex)) and not isinstance(var, bool):
        return True

    # 2. 檢查是否為可能的字串數字
    if isinstance(var, str):
        try:
            float(var) # 嘗試轉換成 float,這會包含整數和浮點數
            return True
        except ValueError:
            return False # 無法轉換成 float,代表不是數字字串

    # 3. (可選)針對特定第三方庫的數字型別做檢查
    # 例如 NumPy, Pandas 等
    # try:
    #     import numpy as np
    #     if isinstance(var, np.number): # np.number 是 NumPy 中所有數字型別的基底類別
    #         return True
    # except ImportError:
    #     pass # 如果沒有安裝 numpy,就跳過這個檢查

    # 如果以上都不是,那就不是我們想要的數字
    return False

print("--- 測試 is_any_number ---")
print(is_any_number(123))         # True (int)
print(is_any_number(123.45))      # True (float)
print(is_any_number(1 + 2j))      # True (complex)
print(is_any_number("123"))       # True (string, can convert to float)
print(is_any_number("-45.67"))    # True (string, can convert to float)
print(is_any_number("1e6"))       # True (string, can convert to float)
print(is_any_number("abc"))       # False (string, cannot convert)
print(is_any_number(True))        # False (bool, we excluded it explicitly)
print(is_any_number(None))        # False
print(is_any_number([1, 2]))      # False
# print(is_any_number(np.int64(5))) # 如果安裝了 numpy,這個會是 True

我的經驗: 這個 `is_any_number` 函數是我在處理來自不同地方的資料時,最常參考的寫法。它涵蓋了大多數常見的場景:原生的數字型別、可以轉換的數字字串,甚至可以擴展到處理 NumPy、Pandas 等庫的數字型別。在實際應用中,你可以根據你專案的需求,決定是否要加入對特定第三方庫的支援。

總結:選擇最適合你的方法

看完這麼多方法,是不是覺得眼花撩亂了呢?別急,讓我幫你整理一下,什麼時候該用什麼方法:

  1. 判斷字串是否只包含數字字元 (0-9): 使用 str.isdigit()
  2. 判斷字串是否包含 Unicode 數字字元 (不含負號、小數點): 使用 str.isnumeric()
  3. 判斷字串是否能轉換成整數 (int): 使用 try-except 搭配 int()
  4. 判斷字串是否能轉換成浮點數 (float) 或整數: 使用 try-except 搭配 float()。這是最常用來判斷「字串是否為數字」的方法。
  5. 精確定義數字模式 (例如,排除逗號、允許特定格式): 使用正規表達式 (re 模組)。
  6. 判斷變數是否為 Python 原生數字型別 (int, float, complex): 使用 isinstance(var, (int, float, complex))
  7. 判斷變數是否為數字,且包含可轉換的數字字串: 結合 isinstance()try-except 的複合函數。

我的肺腑之言: 對於「Python 判斷字串是不是數字」這個核心問題,try-except 搭配 float() 的方法,絕對是大家最常使用、也最推薦的。它簡潔、強大,而且能處理絕大多數的數字表示法。只有當你需要更嚴格的格式控制,或者要判斷的是已經存在的變數型別時,才會考慮其他方法。

常見問題解答 (FAQ)

在使用這些方法時,你可能還會遇到一些小困惑。別擔心,這裡我整理了一些常見問題,並提供詳細解答。

Q1: 我用 `isdigit()` 判斷 `”-123″`,為什麼是 `False`?

詳解: 這完全是因為 `isdigit()` 的設計。`isdigit()` 只檢查字串中的每個字元是否是數字 (0-9)。它並沒有考慮到負號 `-` 是一個獨立的標記,而不是數字本身。所以,當字串中出現負號時,`isdigit()` 就會回傳 `False`。如果你需要判斷包含負號的字串,請務必使用 `try-except` 搭配 `int()` 或 `float()`,或者使用正規表達式。

Q2: `isnumeric()` 和 `isdigit()` 的區別在哪裡?我什麼時候該用哪個?

詳解: 兩者都用於判斷字串是否由數字字元組成,但 `isnumeric()` 的範圍更廣。

  • `isdigit()`: 僅限於 ASCII 數字 (0-9)。
  • `isnumeric()`: 除了 ASCII 數字,還包括 Unicode 中的數字字元,例如中文數字(一、二、三)、羅馬數字(Ⅰ、Ⅱ、Ⅲ),以及一些分數(½)、上標(²)和下標(₃)字元。

如果你處理的資料只包含標準的阿拉伯數字,`isdigit()` 就夠用了。但如果你預期會遇到包含中文數字、或者其他 Unicode 數字符號的字串,那麼 `isnumeric()` 會是更好的選擇。不過,請注意,兩者都無法處理負號或小數點。

Q3: 我有一個字串 `”12.34abc”`,我想判斷它是不是數字。該怎麼辦?

詳解: 這個情況,`isdigit()` 和 `isnumeric()` 都會回傳 `False`。如果你想判斷它是否能被完全轉換成數字,那麼 `try-except` 搭配 `float()` 是你的最佳夥伴。

讓我們看看:

def is_float_strict(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

print(is_float_strict("12.34abc")) # 輸出: False
print(is_float_strict("12.34"))    # 輸出: True
    

所以,`”12.34abc”` 顯然無法被轉換成一個有效的浮點數,因此這個函數會回傳 `False`,這正是我們想要的。

Q4: 我拿到一個變數 `my_var`,我只想知道它是不是 Python 本身的 `int` 或 `float` 型別,應該用什麼方法?

詳解: 這種情況,直接使用 `isinstance()` 函數是最 Pythonic、最清晰的方式。

程式碼如下:

if isinstance(my_var, (int, float)):
    print("my_var 是一個整數或浮點數。")
else:
    print("my_var 不是整數或浮點數。")
    

如果你還想包含複數 (`complex`),可以將 `(int, float)` 改為 `(int, float, complex)`。如果你希望排除布林值 (`True`, `False`),因為它們在 Python 中是 `int` 的子類別,你可以加上一個額外的檢查:

if isinstance(my_var, (int, float)) and not isinstance(my_var, bool):
    print("my_var 是一個真正的數字 (排除布林值)。")
    

Q5: 正規表達式看起來好難,有沒有什麼簡單的方法來判斷一個字串是不是可以轉換成數字?

詳解: 沒錯,正規表達式對於初學者來說確實有點挑戰。對於「判斷一個字串是否可以轉換成數字」這個最常見的需求,我再次強調,`try-except` 搭配 `float()` 是你最好的朋友!

它比正規表達式來得直觀,而且能處理絕大多數情況,包括:

  • 整數:`”123″`, `”-45″`
  • 浮點數:`”123.45″`, `”-6.78″`, `”.5″`, `”5.”`
  • 科學記號:`”1e-3″`, `”2.5E+2″`

只需要短短幾行程式碼,就可以實現強大的判斷功能,真的非常方便!

def is_convertible_to_number(s):
    try:
        float(s)
        return True
    except (ValueError, TypeError): # 加上 TypeError 以防輸入不是字串
        return False

print(is_convertible_to_number("999"))    # True
print(is_convertible_to_number("-0.5"))   # True
print(is_convertible_to_number("1.23e4")) # True
print(is_convertible_to_number("abc"))    # False
print(is_convertible_to_number(None))     # False
    

結論:讓你的 Python 程式碼更穩健!

透過這篇文章的深入探討,相信你對「Python 判斷是不是數字」這個問題,已經有了非常全面的認識。我們從最基礎的 `isdigit()`、`isnumeric()`,到強大的 `try-except` 型別轉換,再到進階的正規表達式,以及直接的型別檢查 `isinstance()`,希望能讓你了解到,針對不同的情境,都有最適合你的工具。

在我看來,對於大多數從外部讀取、需要驗證的字串,try-except 搭配 float() 是最實用、最能解決問題的方法。而當你直接處理變數時,isinstance() 則是你的首選。這些技巧,絕對能讓你的 Python 程式碼更加穩健、可靠,減少不必要的錯誤,讓你在開發的道路上走得更順暢!

記住,程式開發不僅僅是寫出能執行的程式碼,更重要的是寫出正確、穩定、易於維護的程式碼。精準的數字判斷,就是其中一個重要的環節。希望今天的分享,對你有所幫助!祝大家編安!

Python判斷是不是數字