抑制字符串处理为可迭代

更新:

使内置字符串不可迭代的想法是proposed on python.org in 2006.我的问题不同之处在于我试图仅偶尔抑制此功能;仍然这整个线程非常相关.

以下是在试验基础上实施非迭代str的关键comments by Guido

[…] I implemented this (it was really simple to
do) but then found I had to fix tons of places that iterate over
strings. For example:

  • The sre parser and compiler use things like set(“0123456789”) and also iterate over the characters of the input regexp to parse it.

  • difflib has an API defined for either two lists of strings (a typical line-by-line diff of a file), or two strings (a typical
    intra-line diff), or even two lists of anything (for a generalized
    sequence diff).

  • small changes in optparse.py, textwrap.py, string.py.

And I’m not even at the point where the regrtest.py framework even
works (due to the difflib problem).

I’m abandoning this project; the patch is SF patch 1471291. I’m no
longer in favor of this idea; it’s just not practical, and the premise
that there are few good reasons to iterate over a string has been
refuted by the use cases I found in both sre and 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(),如果我希望它的对象被视为可迭代的话.然后每当我需要一个字符串文字时,我会创建一个这个类的对象.

以下是一些与切线相关的问题:

How can I tell if a python variable is a string or a list?

how to tell a variable is iterable but not a string

解决方法:

遗憾的是,没有任何方法可以自动执行此操作.您提出的解决方案(不可迭代的str子类)遇到与isinstance()相同的问题…即,您必须记住在使用字符串的任何地方使用它,因为没有办法让Python使用它代替本地阶级.当然,你无法对内置对象进行修补.

我可能会建议,如果你发现自己编写了一个带有可迭代容器或字符串的函数,那么你的设计可能有问题.但有时你无法避免它.

在我看来,最不干扰的事情就是将检查放入一个函数中,并在进入循环时调用它.这至少会将行为更改放在最有可能看到它的位置:在for语句中,不会被隐藏在类中的某个位置.

def iterate_no_strings(item):
    if issubclass(item, str):   # issubclass(item, basestring) for Py 2.x
        return iter([item])
    else:
        return iter(item)

for thing in iterate_no_strings(things):
    # do something...
上一篇:standby_file_management参数为MANUAL导致添加数据文件错误


下一篇:oracle 单实例DG(切换篇)