不區分大小寫的字串比較

以不區分大小寫的方式比較字串似乎是微不足道的,但事實並非如此。本節僅考慮 unicode 字串(Python 3 中的預設值)。請注意,Python 2 可能具有相對於 Python 3 的微妙弱點 - 後者的 unicode 處理要完整得多。

首先要注意的是,在 unicode 中刪除大小寫的轉換並非易事。有 text.lower() != text.upper().lower() 的文字,如 ß

>>> "ß".lower()
'ß'

>>> "ß".upper().lower()
'ss'

但是,讓我們說你想無比地比較 BUSSEBuße。哎呀,你可能也想比較 BUSSEBUẞE 相等 - 這是更新的資本形式。推薦的方法是使用 casefold

Python 3.x >= 3.3

>>> help(str.casefold)
"""
Help on method_descriptor:

casefold(...)
      S.casefold() -> str
    
     Return a version of S suitable for caseless comparisons.
"""

不要只使用 lower。如果 casefold 不可用,那麼做 .upper().lower() 有幫助(但只是有點)。

那你應該考慮口音。如果你的字型渲染器很好,你可能會認為 "ê" == "ê" - 但它沒有:

>>> "ê" == "ê"
False

這是因為它們實際上是

>>> import unicodedata

>>> [unicodedata.name(char) for char in "ê"]
['LATIN SMALL LETTER E WITH CIRCUMFLEX']

>>> [unicodedata.name(char) for char in "ê"]
['LATIN SMALL LETTER E', 'COMBINING CIRCUMFLEX ACCENT']

解決這個問題最簡單的方法是 unicodedata.normalize。你可能想要使用 NFKD 規範化,但請隨時檢視文件。然後一個人

>>> unicodedata.normalize("NFKD", "ê") == unicodedata.normalize("NFKD", "ê")
True

最後,這裡用函式表示:

import unicodedata

def normalize_caseless(text):
    return unicodedata.normalize("NFKD", text.casefold())

def caseless_equal(left, right):
    return normalize_caseless(left) == normalize_caseless(right)