首页 文章

str.startswith如何真正起作用?

提问于
浏览
16

我一直在玩 startswith() 并且我发现了一些有趣的东西:

>>> tup = ('1', '2', '3')
>>> lis = ['1', '2', '3', '4']
>>> '1'.startswith(tup)
True
>>> '1'.startswith(lis)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: startswith first arg must be str or a tuple of str, not list

现在,错误是显而易见的,并将列表转换为元组将正常工作,就像它在第一时间做的那样:

>>> '1'.startswith(tuple(lis))
True

现在,我的问题是:为什么第一个参数必须是str或str前缀的元组,而不是str前缀列表?

AFAIK, startswith() 的Python代码可能如下所示:

def startswith(src, prefix):
    return src[:len(prefix)] == prefix

但这让我更加困惑,因为即使考虑到它,无论是列表还是元组,它仍然不应该有任何区别 . 我错过了什么?

3 回答

  • 22

    技术上没有理由接受其他序列类型,没有 . source code粗略地这样做:

    if isinstance(prefix, tuple):
        for substring in prefix:
            if not isinstance(substring, str):
                raise TypeError(...)
            return tailmatch(...)
    elif not isinstance(prefix, str):
        raise TypeError(...)
    return tailmatch(...)
    

    (其中tailmatch(...)执行实际的匹配工作) .

    所以是的,任何迭代都可以用于 for 循环 . 但是,所有其他带有多个值的字符串测试API(以及 isinstance()issubclass() )也只接受元组,这会告诉您作为API的用户,可以安全地假设该值不会被突变 . 你不能改变元组,但理论上该方法可以改变列表 .

    另请注意,您通常会测试固定数量的前缀或后缀或类(在 isinstance()issubclass() 的情况下);该实现不适合大量元素 . 元组意味着您具有有限数量的元素,而列表可以是任意大的 .

    接下来,如果任何可迭代或序列类型是可接受的,那么这将包括字符串;单个字符串也是一个序列 . 那么单个字符串参数应该被视为单独的字符,还是单个前缀?

    换句话说,自我文档的限制是序列不会被变异,与其他API一致,它带有有限数量的项目的含义来测试,并消除了关于如何单个字符串的歧义论证应该被对待 .

    请注意,这是在Python Ideas列表之前提出的;见this thread; Guido van Rossum 's main argument there is that you either special case for single strings or for only accepting a tuple. He picked the latter and doesn' t看到需要改变这一点 .

  • 2

    几年前已经在Python-ideas上提出了这个问题:str.startswith taking any iterator instead of just tuple和GvR有this to say

    当前的行为是故意的,字符串本身是可迭代的模糊性是主要原因 . 因为无论如何,几乎总是用文字或文字元组调用startswith(),我认为没有必要扩展语义 .

    除此之外,似乎没有真正的动机为什么这样做 .

    当前的方法使事情简单快速,unicode_startswith(和 endswith )检查元组参数,然后检查字符串1 . 然后他们按适当的方向调用tailmatch . 可以说,这在当前状态下很容易理解,即使对于C代码的陌生人也是如此 .

    添加其他情况只会导致更加臃肿和复杂的代码,几乎没有什么好处,同时还需要对unicode对象的任何其他部分进行类似的更改 .

  • 19

    在类似的说明中,这里讨论了关于某些字符串方法的API设计选择,包括recent changes to the str.startswith signature . 虽然他简要地提到了这个事实,即 str.startswith 接受了一个字符串或字符串元组并且没有进行阐述,但是关于核心开发人员和贡献者在处理现有API时所做出的决策和痛点,这个话题都是有用的 .

相关问题