Python中startswith()传入元组返回错误结果的原因排查
Python startswith()传入元组时的匹配异常问题
问题现象
想要仅匹配以%%ABC XYZ:或%%RLMI UUEW:开头的字符串,但使用startswith()传入元组作为参数时出现异常结果:
'ABC XYZ:0882-928'.startswith(('%%RLMI UUEW:','%%ABC XYZ:')) # Out[1]: True '%%ABC XYZ:0882-928'.startswith(('%%RLMI UUEW:','%%ABC XYZ:')) # Out[2]: True
而传入单个子串时结果符合预期:
'ABC XYZ:7281-001'.startswith('%%ABC XYZ:') # Out[3]: False '%%ABC XYZ:7281-001'.startswith('%%ABC XYZ:') # Out[4]: True
使用的Python版本为3.9.13:
import sys print("User Current Version:-", sys.version) # User Current Version:- 3.9.13 (main, Aug 25 2022, 23:51:50) [MSC v.1916 64 bit (AMD64)]
原因分析
这是Python 3.9及更早版本的已知bug:当startswith()传入包含空格的前缀元组时,内部匹配逻辑会错误地忽略前缀开头的部分字符,导致不完整的前缀被匹配。
比如示例中'ABC XYZ:0882-928'被错误匹配,是因为它和元组内'%%ABC XYZ:'的后半段'ABC XYZ:'吻合,而非完整前缀。该bug在Python 3.10及后续版本中已被修复,升级后startswith()会严格匹配元组内的完整前缀,返回正确结果。
替代解决方案
如果暂时无法升级Python版本,可采用以下两种方法实现正确匹配:
- 分别调用
startswith()并通过逻辑或连接:s = 'ABC XYZ:0882-928' result = s.startswith('%%RLMI UUEW:') or s.startswith('%%ABC XYZ:') # result: False - 使用正则表达式匹配字符串开头:
import re s = 'ABC XYZ:0882-928' result = re.match(r'^(%%ABC XYZ:|%%RLMI UUEW:)', s) is not None # result: False
内容的提问来源于stack exchange,提问作者Rasec Malkic
相关产品推荐
相关产品推荐

