更新:
在Python官网的讨论中,有人提出了使内置字符串不可迭代的想法。我的问题不同之处在于,我只是偶尔想要关闭这个功能;但整个讨论仍然非常相关。
以下是由Guido发表的关键评论,他试行了非可迭代str
:
[...] 我实现了这个(真的很简单),但后来发现我必须修复大量遍历字符串的地方。例如:
sre解析器和编译器使用像set("0123456789")这样的东西,并且还要遍历输入正则表达式的字符来解析它。
difflib为两个字符串列表(文件的典型逐行差异)或两个字符串(典型的行内差异)定义了API,甚至可以为任意两个列表(用于一般序列差异)进行比较。
optparse.py、textwrap.py和string.py的小更改。
我还没有到使regrtest.py框架工作的地步(由于difflib问题)。
我放弃了这个项目;补丁是SF补丁1471291。我不再支持这个想法;它不切实际,而且有关于循环遍历字符串的好理由被反驳了,这些理由可以在sre和difflib中找到。
原始问题:
虽然字符串是一个可迭代对象,这是语言的一个很好的特性,但当与鸭子类型结合时,它可能会导致灾难:
# record has to support [] operation to set/retrieve values
# fields has to be an iterable that contains the fields to be set
def set_fields(record, fields, value):
for f in fields:
record[f] = value
set_fields(weapon1, ('Name', 'ShortName'), 'Dagger')
set_fields(weapon2, ('Name',), 'Katana')
set_fields(weapon3, 'Name', 'Wand') # I was tired and forgot to put parentheses
不会引发异常,除非在众多地方测试isinstance(fields, str)
,否则没有简单的方法可以捕获这个问题。在某些情况下,这个 bug 将需要花费很长时间才能找到。
我想在我的项目中完全禁用把字符串当做可迭代对象,这是一个好主意吗?能否轻松、安全地实现?
也许我可以子类化内置的 str
类,以便如果我想要将其对象视为可迭代对象,则需要显式调用 get_iter()
。然后,每当我需要字符串字面值时,我将创建此类的对象。
以下是一些有关的问题:
isinstance(fields, str)
检查 - 您不太可能需要创建自己的类,使其像字符串一样。或者,将fields
设为最后一个可变参数。 (如果您感到疲倦并忘记 不 应该在它周围加括号,则无法帮助您)。 - millimoose