防止 Python 的 for 循环遍历单个字符串的每个字符

8
我有一个变量,它可以是单个字符串或字符串列表。当变量是单个字符串时,循环按字符迭代它。
text = function() # the function method can return a single string or list of string
for word in text:
    print word+"/n"
# When it is a single string , it prints char by char.

当字符串只有一个时,我希望循环只迭代一次。我实际上不想使用其他类型的循环。如何使用 for each 结构来实现?


2
像这样吗?https://dev59.com/AnE95IYBdhLWcg3wn_f2 - Christoph Bluoss
2
检查 text 的类型怎么样? - Mohammad
如果是单个字符串,您可以将其作为仅包含一个元素的列表返回。 - chatton
6个回答

11

如果您的函数始终返回一个列表,即使其中只有一个元素,那将更加简洁。如果可以更改您的代码,我强烈建议您这样做。

否则,请在您的循环之前添加此行:

text = text if isinstance(text, list) else [text]

此外,你的变量名很令人困惑,你应该将"文本"称为"单词列表"或其他名称,以更好地指示所需的类型。

需要类型检查通常表示风格存在问题。


谢谢,显然,这里的列表让我感到困惑 :) - Falk Schuetzenmeister

1
这应该可以做到:

text = function() 
if isinstance(text, list):
    for word in text:
        print word + "/n"
else:
    print text + "/n"

这不是 Pythonic 的做法,因为如果 function() 返回一个字符串元组,则您的代码将尝试将整个元组作为一个单词打印。 - A Kareem
从问题中可以明显看出,该函数返回的要么是字符型数据,要么是字符串列表,而不是元组。 - Fejs

1
我选择这个方法是因为它强调了循环的准备工作,而不是基本的循环(重新)设计。
if type(thing) is str:
    x = [thing]
elif type(thing) is list:
    x = thing[:]

for i in x:
   ... do stuff ....

0

尽管鸭子类型是常态,但有时您必须检查某个东西的类型。在这种情况下,您期望某些实例为basestring

text = function()
if isinstance(text, basestring):
    print text
else:
    for word in text:
        print word

1
basestring 只适用于 Python2。 - tacaswell
@tacaswell 的 "python-2.7" 标签 - Brian
无法再更改我的投票了。最好使用 sixpies - tacaswell
还有代码中的print语句,因此您需要导入print_function。我们一定读了不同的问题。 - Brian

0
你需要使用isinstance()方法来检查变量所持有的值的类型,根据文档:

如果对象参数是类信息参数的实例或其(直接、间接或虚拟)子类,则返回true。

使用该方法,您可以创建自定义函数,如下所示:

import collections

def my_print(my_val):
    if isinstance(my_val, str):
        print my_val
    elif isinstance(my_val, collections.Iterable):  # OR, use `list` if you just want check for list object
        # To check object is iterable ^
        for val in my_val:
            print val
    else:
       raise TypeError('Unknown value')

示例运行:

>>> my_print('Hello')
Hello
>>> my_print(['Hello', 'World'])
Hello
World

instance() 函数用于检查传递的对象是否为指定类的实例。

>>> isinstance('hello', str)
True
>>> isinstance('hello', list)
False

或者,您可以使用 type() 检查变量类型:

>>> type('hello') == str
True

这将会因为tuples而失败。 - tacaswell
@tacaswell:感谢您的评论。已更新。 - Moinuddin Quadri
你只需要特别处理str类型,让鸭子类型来处理其他情况。 - tacaswell
我专门处理这种情况,当int或任何其他值传递给函数时。 - Moinuddin Quadri

0

通过鸭子类型仍然可以实现,你只需要在列表上使用一个字符串没有的方法或者在字符串上使用一个列表没有的方法,并捕获异常,例如copy()是列表的方法而不是字符串的方法。

text = function()
try:
    temp_text = text.copy()
    for word in text:
        print word
except AttributeError:
    print text

在上面的代码中,如果function()返回一个字符串,text.copy()将引发AttributeError异常,并且不会通过for循环,而是进入异常块并打印原始文本。另一方面,如果text.copy()成功,那么它就是一个列表,并且继续进入for循环以打印列表中的每个单词。

你可以只检查属性而不实际执行方法:assert(hasattr(text, 'copy'))。如果这是假的,你会得到一个AssertionError。尽管有人说引发异常比类型检查更好,但哪种方法表现更好仍然很有趣。 - Falk Schuetzenmeister

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接