在另一个询问如何在不使用 str.split 的情况下获取字符串的第一个单词的问题中,一些用户提出了以下想法。
word = s[:s.find(' ')]
Run Code Online (Sandbox Code Playgroud)
只要字符串s包含空格,它就会起作用。尽管如果它不包含一个,这会默默地失败。
s = 'foo'
word = s[:s.find(' ')] # 'fo'
Run Code Online (Sandbox Code Playgroud)
这是因为当未找到子字符串时str.find返回。-1
由于以下原因,这似乎是一个奇怪的设计选择。
-1实际上是一个正确的索引
解释为 a bool,它在上下文中没有任何有用的含义
None似乎是一个更好的候选者(并且将使上面的代码工作)
是否有一个好的设计原因或用例为什么-1选择作为返回值str.find而不是None当没有找到子字符串时?
感谢您提出这个问题,因为我很惊讶查找示例的展示没有提到这个问题。我同意你的推理,但我一直无法为如此重要的实施决定找到具体的理由。
如果您查看find 方法及其最重要的实现组件fastsearch,您将看到它-1在无法找到子字符串时返回,如文档中所述。然而,代码中没有任何迹象解释为什么要这样编写。有趣的是,其中一条评论包括有关该返回值的警告,表明开发人员意识到这个细节是一个怪癖。
想象一下,您有一些字符串,其中包含基于小写无空格公司名称的 id inc,这些 id 可能以 结尾,您希望将其删除以对其进行规范化。
在典型场景中,您可以执行以下操作:
s = "fastcareinc"
idx = s.find("inc")
>>> s[:idx]
'fastcare'
Run Code Online (Sandbox Code Playgroud)
但是,如果名称已经采用规范化形式,则最终会遇到严重错误,导致 id 的错误表示:
s = "fastcare"
idx = s.find("inc")
>>> s[:idx]
'fastcar'
Run Code Online (Sandbox Code Playgroud)
上面,名称已从 更改为"fastcare","fastcar"因为变量idx是-1,因此切片会删除 中的最后一个字符s。如果str.find返回None,那就不是问题了:
s = "fastcare"
idx = None
>>> s[:idx]
'fastcare'
Run Code Online (Sandbox Code Playgroud)
解决此问题的最佳方法是通过 cPython 的 PR 在 Python 社区中表达它。不过,目前我建议您使用str.indexin代替str.find来避免在生产代码中出现这种情况。或者,我根据概述的场景提出一种解决方法,可以让您远离该错误:
>>> s[:None if (idx := s.find("inc")) == -1 else idx]
'fastcare'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
697 次 |
| 最近记录: |