这是我通常所做的,以确定输入是一个列表/元组-而不是一个str。因为很多次我偶然发现错误,其中一个函数错误地传递了一个str对象,而目标函数在lst中执行x,假设lst实际上是一个列表或元组。

assert isinstance(lst, (list, tuple))

我的问题是:有没有更好的方法来实现这个目标?


当前回答

duck-typing的另一个版本,用于帮助区分类似字符串的对象和其他类似序列的对象。

类字符串对象的字符串表示就是字符串本身,所以你可以检查你是否从str构造函数返回了一个相等的对象:

# If a string was passed, convert it to a single-element sequence
if var == str(var):
    my_list = [var]

# All other iterables
else: 
    my_list = list(var)

这应该适用于所有与str兼容的对象和所有类型的可迭代对象。

其他回答

带有PHP风格的Python:

def is_array(var):
    return isinstance(var, (list, tuple))

一般来说,迭代对象的函数不仅适用于元组和列表,也适用于字符串,这是一个特性而不是缺陷。您当然可以使用isinstance或duck类型来检查参数,但为什么要这样做呢?

这听起来像是一个反问句,但事实并非如此。“为什么我要检查参数的类型?”这个问题的答案很可能是针对实际问题的解决方案,而不是感知到的问题。为什么将字符串传递给函数是一个bug ?另外:如果将字符串传递给这个函数是一个bug,那么如果将其他一些非列表/元组可迭代对象传递给它也是一个bug吗?为什么,或者为什么不?

我认为这个问题最常见的答案可能是,编写f(“abc”)的开发人员希望函数的行为就像他们编写的f([“abc”])一样。在某些情况下,保护开发人员不受自己的伤害比支持在字符串中遍历字符的用例更有意义。但我会先好好想想。

我在测试用例中这样做。

def assertIsIterable(self, item):
    #add types here you don't want to mistake as iterables
    if isinstance(item, basestring): 
        raise AssertionError("type %s is not iterable" % type(item))

    #Fake an iteration.
    try:
        for x in item:
            break;
    except TypeError:
        raise AssertionError("type %s is not iterable" % type(item))

没有在发电机上进行测试,我认为如果通过发电机,你会在下一次“屈服”时留下,这可能会把下游的事情搞砸。不过,这是一个unittest

我在tensorflow中找到了这样一个名为is_sequence的函数。

def is_sequence(seq):
  """Returns a true if its input is a collections.Sequence (except strings).
  Args:
    seq: an input sequence.
  Returns:
    True if the sequence is a not a string and is a collections.Sequence.
  """
  return (isinstance(seq, collections.Sequence)
and not isinstance(seq, six.string_types))

我已经核实了,它符合你的需求。

就这么做

if type(lst) in (list, tuple):
    # Do stuff