抑制字符串的迭代处理 [英] Suppressing treatment of string as iterable

查看:67
本文介绍了抑制字符串的迭代处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:

使内置字符串不可迭代的想法是在2006年在python.org上提出.我的问题有所不同,因为我试图偶尔仅抑制一次此功能.整个线程还是很相关的.

An idea to make built-in strings non-iterable was proposed on python.org in 2006. My question differs in that I'm trying to only suppress this features once in a while; still this whole thread is quite relevant.

以下是关键的 Guido的评论谁在试用的基础上实施了不可迭代的str:

Here are the critical comments by Guido who implemented non-iterable str on a trial basis:

[...]我实现了这一点( ),但后来我不得不修复大量遍历的地方 字符串.例如:

[...] 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:

  • sre解析器和编译器使用set("0123456789")之类的东西,并且还对输入正则表达式的字符进行迭代以对其进行解析.

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

difflib为两个字符串列表(一个文件的典型逐行差异)或两个字符串(一个典型的字符串)定义了一个API 行内差异),甚至两个东西的列表(用于广义 序列差异).

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).

optparse.py,textwrap.py,string.py中的微小变化.

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

我什至不知道regrtest.py框架 有效(由于difflib问题).

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

我正在放弃这个项目;该补丁是SF补丁1471291.我不是 不再支持这个想法;这只是不切实际的前提 几乎没有充分的理由来遍历字符串 我在sre和difflib中都发现了用例,对此提出了反驳.

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.

原始问题:

虽然字符串的可重复性是该语言的一个很好的功能,但是当它与鸭子输入结合使用时,可能会导致灾难:

While it's a neat feature of the language that a string is an iterable, when combined with the duck typing, it may lead to disaster:

# 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)之外,没有简单的方法来捕获此异常.在某些情况下,此错误将需要很长时间才能找到.

No exception will be raised, and there's no easy way to catch this except by testing for isinstance(fields, str) in a myriad places. In some circumstances, this bug will take a very long time to find.

我想在我的项目中完全禁止将字符串视为可迭代对象.这是个好主意吗?可以轻松,安全地完成吗?

I want to disable strings from being treated as an iterable entirely in my project. Is it a good idea? Can it be done easily and safely?

也许我可以将内置的str子类化,这样,如果我希望将其对象视为可迭代对象,就需要显式调用get_iter().然后,每当我需要字符串文字时,我都会创建此类的对象.

Perhaps I could subclass built-in str such that I would need to explicitly call get_iter() if I wanted its object to be treated as an iterable. Then whenever I need a string literal, I would instead create an object of this class.

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

Here are some tangentially related questions:

如何我可以判断python变量是字符串还是列表?

如何判断变量是否可迭代但不是字符串

推荐答案

没有任何方法可以自动执行此操作.您提出的解决方案(不可迭代的str子类)与isinstance()一样存在同样的问题……也就是说,您必须记住在使用字符串的任何地方都使用它,因为无法制作Python用它代替本地类.当然,您不能用猴子修补内置对象.

There aren't any ways to do this automatically, unfortunately. The solution you propose (a str subclass that isn't iterable) suffers from the same problem as isinstance() ... namely, you have to remember to use it everywhere you use a string, because there's no way to make Python use it in place of the native class. And of course you can't monkey-patch the built-in objects.

我可能建议,如果您发现自己编写的函数使用一个可迭代的容器一个字符串,则可能是您的设计有问题.有时候,您还是无法避免.

I might suggest that if you find yourself writing a function that takes either an iterable container or a string, maybe there's something wrong with your design. Sometimes you can't avoid it, though.

在我看来,要做的最不麻烦的事情是将检查放入函数中,并在进入循环时调用该函数.至少这会将行为更改放在您最有可能看到的位置:在for语句中,不要埋藏在类中的某个地方.

In my mind, the least intrusive thing to do is to put the check into a function and call that when you get into a loop. This at least puts the behavior change where you are most likely to see it: in the for statement, not buried away somewhere in a class.

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...

这篇关于抑制字符串的迭代处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆