问题 类型检查:不是字符串的可迭代类型


为了更好地解释,请考虑这种简单的类型检查功能:

from collections import Iterable
def typecheck(obj):
    return not isinstance(obj, str) and isinstance(obj, Iterable)

如果 obj 是一个可迭代的类型 str,它回来了 True。但是,如果 obj 是一个 str 或者是不可迭代的类型,它返回 False

有没有办法更有效地执行类型检查?我的意思是,检查类型似乎有点多余 obj 曾经看过它是不是一个 str 然后检查一下 再次 看看它是否可迭代。

我想除了列出其他所有可迭代类型 str 喜欢这个:

return isinstance(obj, (list, tuple, dict,...))

但问题是该方法将错过任何未明确列出的其他可迭代类型。

所以...有什么更好的,或者我在函数中给出的方法效率最高?


6050
2017-11-13 01:42


起源

这不是低效的。您可能需要担心更重要的事情。 - arshajii
@thefourtheye - 因为有时您需要检查某些东西是否可迭代但不是字符串。示例可以是展平嵌套列表的函数。你不希望它中的字符串变平。 - iCodez
@iCodez:但你希望这些词汇变平了吗?还是文件?在这种特定情况下,专门检查列表似乎更合理。也就是说,有合法的用例,你想要接受一个字符串或一系列字符串,你想要区分这两者。 - user2357112
如果排除str,通常也应排除unicode和buffer - Leonardo.Z
@aIKid - 是的,我不喜欢 isinstance(obj, (list, tuple, dict,...)) 解决方案太多了。我只是好奇,如果有任何方法可以不打电话 isinstance 两次。但现在我开始认为那样 是 实际上是最好的方式。 - iCodez


答案:


python 2.x,检查 __iter__ 属性是有用的(虽然并不总是明智的),因为iterables应该具有此属性,但字符串不具有此属性。

def typecheck(obj): return hasattr(myObj, '__iter__')

不好的是那个 __iter__ 并不是真正的Pythonic方法:有些对象可能会实现 __getitem__ 但不是 __iter__ 例如。

Python 3.x,字符串得到了 __iter__ 属性,破坏了这个方法。

您列出的方法是我在Python 3.x中知道的最有效的Pythonic方法:

def typecheck(obj): return not isinstance(obj, str) and isinstance(obj, Iterable)

有一种更快(更有效)的方式,即检查 __iter__ 喜欢在Python 2.x中,然后再检查 str

def typecheck(obj): return hasattr(obj, '__iter__') and not isinstance(obj, str)

这与Python 2.x中的注意事项相同,但速度要快得多。


12
2017-11-13 02:46



还有一个明显的问题 isinstance(u'foo', str) 回报 False 所以你最终会遇到明确列出所有类型的难题 不 字符串类型。作为一个快速的黑客,我想出了检查 hasattr(thing, 'lower') 但它显然太模糊了。 - tripleee
@tripleee - isinstance(u'foo', basestring) 在Python 2.x中做的伎俩(两者都有 unicode 和 str 子类 basestring) - ukrutt


我用这个代码检查它,它适用于Python 2和3

from __future__ import unicode_literals
import types
import collections

var = ["a", "b", "c"]
if isinstance(var, collections.Iterable) and \
        not isinstance(var, types.StringTypes):
    return var

0
2018-03-20 09:21



模 types 没有属性 StringTypes 在Python 3.6中 - Jerry Smith