转换为大写/小写时,字符串是否会变短?

时间:2015-02-24 11:59:24

标签: python string python-3.x unicode

转换为大写或小写时,字符串可能会变长(就Unicode代码点而言)。例如,'ß'.upper()评估为'SS'。但是有些字符串缩短了吗?也就是说,是否存在字符串s,使得表达式

len(s.lower()) < len(s) or len(s.upper()) < len(s)

评估为True

1 个答案:

答案 0 :(得分:4)

我认为这可能是依赖于实现的。我将根据CPython源代码回答。

在我看来,有两种可能的情况,在字符串上调用lower可以缩短它。

  1. 两个相互匹配的Unicode点的某些组合会转换为一个Unicode点。
  2. 单个Unicode点将转换为空字符串。
  3. 我们可以通过检查内部小写转换函数的类型签名来确定案例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,相应的列表推导同样返回一个空列表。

    结论

    不,lowerupper永远不会缩短任何内容。