转换为大写或小写时,字符串可能会变长(就Unicode代码点而言)。例如,'ß'.upper()
评估为'SS'
。但是有些字符串缩短了吗?也就是说,是否存在字符串s
,使得表达式
len(s.lower()) < len(s) or len(s.upper()) < len(s)
评估为True
?
答案 0 :(得分:4)
我认为这可能是依赖于实现的。我将根据CPython源代码回答。
在我看来,有两种可能的情况,在字符串上调用lower
可以缩短它。
我们可以通过检查内部小写转换函数的类型签名来确定案例1是否可行。这是Objects/unicodectype.c。
int _PyUnicode_ToLowerFull(Py_UCS4 ch, Py_UCS4 *res)
{
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
if (ctype->flags & EXTENDED_CASE_MASK) {
int index = ctype->lower & 0xFFFF;
int n = ctype->lower >> 24;
int i;
for (i = 0; i < n; i++)
res[i] = _PyUnicode_ExtendedCase[index + i];
return n;
}
res[0] = ch + ctype->lower;
return 1;
}
我不是100%理解这段代码,但我发现第一个参数ch
是一个单独的Unicode点。由于它只对单个字符而不是字符组合起作用,因此似乎排除了案例1;代码点的组合不会变成更小的序列。
通过这种方式,我们可以通过迭代到sys.maxunicode
来确定案例2是否发生,并且在降低后查看任何单个值的长度是否为零。
>>> import sys
>>> unicode_chars = list(map(chr, range(sys.maxunicode+1)))
>>> [x for x in unicode_chars if len(x.lower()) == 0]
[]
看起来案例2也被破坏了。
我们也可以将上述逻辑应用于upper
。对于案例1,_PyUnicode_ToUpperFull
的实施几乎与其较低的对应物相同;对于案例2,相应的列表推导同样返回一个空列表。
不,lower
和upper
永远不会缩短任何内容。