最近在阅读关于忽略大小写时使用casefold和字符串比较的内容。我了解到MSDN标准是使用InvariantCulture并且绝对避免使用toLowerCase。然而,从我所了解的情况来看,casefold更像是一种更积极的toLowerCase。我的问题是,我应该在Python中使用casefold,还是有更符合Python语言习惯的标准可以使用?另外,casefold是否通过了Turkey测试?
最近在阅读关于忽略大小写时使用casefold和字符串比较的内容。我了解到MSDN标准是使用InvariantCulture并且绝对避免使用toLowerCase。然而,从我所了解的情况来看,casefold更像是一种更积极的toLowerCase。我的问题是,我应该在Python中使用casefold,还是有更符合Python语言习惯的标准可以使用?另外,casefold是否通过了Turkey测试?
1) 在Python 3中,应该使用casefold()
实现不区分大小写的字符串匹配。
从Python 3.0开始,字符串以Unicode形式存储。 Unicode标准第3.13章节将默认的不区分大小写匹配定义为:
当且仅当 toCasefold(X) = toCasefold(Y) 时,字符串X与字符串Y相等。
2) 在Python 3.6中,casefold()不能通过Turkey Test。
对于两个字符,大写字母I和带点的大写字母İ,Unicode标准定义了两个不同的大小写转换映射。
默认的(非土耳其语):
I → i (U+0049 → U+0069)
İ → i̇ (U+0130 → U+0069 U+0307)
替代方案(土耳其语):
I → ı (U+0049 → U+0131)
İ → i (U+0130 → U+0069)
Python的casefold()
只能应用默认映射,无法通过Turkey Test。例如,土耳其单词“LİMANI”和“limanı”是不区分大小写的等价词,但是"LİMANI".casefold() == "limanı".casefold()
返回False
。没有选项可以启用替代映射。
3) 如何在Python 3中进行不区分大小写的字符串匹配。
Unicode标准第3.13章节描述了几种不区分大小写的匹配算法。规范化不区分大小写匹配可能适用于大多数情况。该算法已经考虑了所有边角情况。我们只需要添加一个选项来切换非土耳其语和土耳其语大小写转换。
import unicodedata
def normalize_NFD(string):
return unicodedata.normalize('NFD', string)
def casefold_(string, include_special_i=False):
if include_special_i:
string = unicodedata.normalize('NFC', string)
string = string.replace('\u0049', '\u0131')
string = string.replace('\u0130', '\u0069')
return string.casefold()
def casefold_NFD(string, include_special_i=False):
return normalize_NFD(casefold_(normalize_NFD(string), include_special_i))
def caseless_match(string1, string2, include_special_i=False):
return casefold_NFD(string1, include_special_i) == casefold_NFD(string2, include_special_i)
casefold_()
是Python中casefold()
的包装器。如果将其参数include_special_i
设置为True
,则应用土耳其映射,如果设置为False
,则使用默认映射。
caseless_match()
对string1
和string2
进行规范的不区分大小写匹配。如果字符串是土耳其单词,则必须将include_special_i
参数设置为True
。
示例:
>>> caseless_match('LİMANI', 'limanı', include_special_i=True)
True
>>> caseless_match('LİMANI', 'limanı')
False
>>> caseless_match('INTENSIVE', 'intensive', include_special_i=True)
False
>>> caseless_match('INTENSIVE', 'intensive')
True
casefold_
函数不需要以_
结尾,因为它没有遮蔽内置函数或关键字。 - Gringo Suave
casefold
的作用在文档中已经解释了。