我应该使用 Python 的 casefold() 函数吗?

9

最近在阅读关于忽略大小写时使用casefold和字符串比较的内容。我了解到MSDN标准是使用InvariantCulture并且绝对避免使用toLowerCase。然而,从我所了解的情况来看,casefold更像是一种更积极的toLowerCase。我的问题是,我应该在Python中使用casefold,还是有更符合Python语言习惯的标准可以使用?另外,casefold是否通过了Turkey测试?


2
  1. casefold 的作用在文档中已经解释了。
  2. 在这种情况下,"better" 是什么意思?
  3. 什么是土耳其测试(Turkish Test),你有尝试运行它来找出答案吗?
- jonrsharpe
@jonrsharpe 抱歉,我的意思是更符合Python风格,也是指Turkey Test。我只想知道优秀的程序员在Python中进行无大小写比较时使用什么。 - FlyingLightning
@jonrsharpe - 这里更详细地描述了土耳其测试https://dev59.com/O3RA5IYBdhLWcg3w4R_o#797043 - Sean Vieira
1
你尝试过使用casefold来亲自验证它是否通过了土耳其测试吗? - jonrsharpe
@jonrsharpe 我真的还没有时间尝试它。我也还没有遇到需要使用casefold的情况。这只是在进行一些空闲研究后我脑海中出现的一个问题。如果我确实有机会测试它,我会确保发布我的结果。最后,我最大的问题仍然是:是否casefold是忽略大小写的最pythonic的方法? - FlyingLightning
1个回答

19

1) 在Python 3中,应该使用casefold()实现不区分大小写的字符串匹配。

从Python 3.0开始,字符串以Unicode形式存储。 Unicode标准第3.13章节默认的不区分大小写匹配定义为:

当且仅当 toCasefold(X) = toCasefold(Y) 时,字符串X与字符串Y相等。

Python的casefold()实现了Unicode的toCasefold()。因此,它应该用于实现不区分大小写的字符串匹配。尽管如此,单独使用casefolding不能覆盖某些极端情况并通过Turkey Test(参见第3点)。

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()string1string2进行规范的不区分大小写匹配。如果字符串是土耳其单词,则必须将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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接