当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何判断变量是可迭代的但不是字符串》经验,为你挑选了3个好方法。

我有一个函数接受一个参数,可以是单个项目或双项目:

def iterable(arg)
    if #arg is an iterable:
        print "yes"
    else:
        print "no"

以便:

>>> iterable( ("f","f") )
yes

>>> iterable( ["f","f"] )
yes

>>> iterable("ff")
no

问题是字符串在技术上是可迭代的,所以我不能在尝试时捕获ValueError arg[1].我不想使用isinstance(),因为这不是很好的做法(或者我被告知).



1> scvalex..:

使用isinstance(我不明白为什么这是不好的做法)

import types
if not isinstance(arg, types.StringTypes):

请注意StringTypes的使用.它确保我们不会忘记一些不起眼的字符串.

从好的方面来说,这也适用于派生的字符串类.

class MyString(str):
    pass

isinstance(MyString("  "), types.StringTypes) # true

此外,您可能想看看上一个问题.

干杯.


注:行为在Python 3的改变StringTypesbasestring不再定义.根据您的需求,您可以取代他们isinstancestr,或子集元组(str, bytes, unicode),例如用于用Cython用户.正如@Theron Luhn所提到的,你也可以使用six.


-1,即使输入是数字,函数,类,条件也将是"真".
我认为糟糕的做法是因为[鸭子打字](http://en.wikipedia.org/wiki/Duck_typing)原则.作为特定类的成员并不意味着它是可以使用的_only_对象,也不意味着预期的方法可用.但我认为有时你甚至无法推断出该方法的作用,即使它存在,所以`isinstance`可能是唯一的方法.

2> sorin..:

截至2017年,这是一个适用于所有Python版本的可移植解决方案:

#!/usr/bin/env python
import collections
import six


def iterable(arg):
    return (
        isinstance(arg, collections.Iterable) 
        and not isinstance(arg, six.string_types)
    )


# non-string iterables    
assert iterable(("f", "f"))    # tuple
assert iterable(["f", "f"])    # list
assert iterable(iter("ff"))    # iterator
assert iterable(range(44))     # generator
assert iterable(b"ff")         # bytes (Python 2 calls this a string)

# strings or non-iterables
assert not iterable(u"ff")     # string
assert not iterable(44)        # integer
assert not iterable(iterable)  # function



3> Alex Martell..:

从Python 2.6开始,引入抽象基类isinstance(用于ABCs,而不是具体类)现在被认为是完全可以接受的.特别:

from abc import ABCMeta, abstractmethod

class NonStringIterable:
    __metaclass__ = ABCMeta

    @abstractmethod
    def __iter__(self):
        while False:
            yield None

    @classmethod
    def __subclasshook__(cls, C):
        if cls is NonStringIterable:
            if any("__iter__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

这是完全相同的副本(只改变类名)Iterable中定义_abcoll.py(的实现细节collections.py)...的原因,这可以作为你想,虽然collections.Iterable不,是,后者更是不辞辛劳,以确保字符串通过Iterable.register(str)在此class语句之后显式调用,可以认为是可迭代的.

当然,__subclasshook__通过Falseany调用其他类之前返回来扩展很容易,这些类要从定义中明确排除.

在任何情况下,导入这个新模块之后myiter,isinstance('ciao', myiter.NonStringIterable)将会False,并且isinstance([1,2,3], myiter.NonStringIterable)将会True像您要求的那样 - 在Python 2.6及更高版本中,这被认为是体现此类检查的正确方法...定义一个抽象基类并检查isinstance它.

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有