Python:检查对象是否是序列
在python中,有没有一种简单的方法来判断某个东西是否不是序列?我试着做:Python:检查对象是否是序列,python,if-statement,sequence,sequences,Python,If Statement,Sequence,Sequences,在python中,有没有一种简单的方法来判断某个东西是否不是序列?我试着做: 如果x不是序列但python不喜欢这样iter(x)将引发类型错误,如果x不能被迭代——但该检查“接受”集合和字典,尽管它“拒绝”其他非序列,如None和数字 另一方面,字符串(大多数应用程序需要考虑的是单个项而不是序列)实际上是序列(因此,任何测试,除非字符串专用,都要确认它们是)。因此,这种简单的检查往往是不够的 在Python2.6及更高版本中,引入了抽象基类,在其他强大功能中,它们为此类“类别检查”提供了更好、
如果x不是序列
但python不喜欢这样iter(x)
将引发类型错误
,如果x
不能被迭代——但该检查“接受”集合和字典,尽管它“拒绝”其他非序列,如None
和数字
另一方面,字符串(大多数应用程序需要考虑的是单个项而不是序列)实际上是序列(因此,任何测试,除非字符串专用,都要确认它们是)。因此,这种简单的检查往往是不够的
在Python2.6及更高版本中,引入了抽象基类,在其他强大功能中,它们为此类“类别检查”提供了更好、系统化的支持 你会注意到字符串仍然被认为是“序列”(因为它们是),但至少你得到了dicts和set。如果要从“序列”的概念中排除字符串,可以使用集合.MutableSequence
(但这也排除元组,元组与字符串一样是序列,但不是可变的),或者显式执行:
import collections
def issequenceforme(obj):
if isinstance(obj, basestring):
return False
return isinstance(obj, collections.Sequence)
调味,趁热享用!-)
PS:对于Python3,使用
str
而不是basestring
,对于Python3.3+:像Sequence
这样的抽象基类已经移动到集合。abc
为什么要这样做?这里的正常方法是需要某种类型的东西(序列、数字或类似文件的对象等),然后在不检查任何东西的情况下使用它。在Python中,我们通常不使用类来携带语义信息,而只是使用定义的方法(这称为“duck类型”)。我们也更喜欢API,因为我们确切地知道预期的结果;如果要更改函数的工作方式,请使用关键字参数、预处理或定义其他函数。描述了以下序列类型:字符串、Unicode字符串、列表、元组、缓冲区和xrange
def isSequence(obj):
return type(obj) in [str, unicode, list, tuple, buffer, xrange]
为什么要问为什么
尝试获取长度,如果异常返回false
def haslength(seq):
try:
len(seq)
except:
return False
return True
由于Python“坚持”duck类型,其中一种方法是检查对象是否有成员(方法)
序列具有长度、项目序列,并支持切片[]。所以,它是这样的:
def is_sequence(obj):
t = type(obj)
return hasattr(t, '__len__') and hasattr(t, '__getitem__')
# additionally: and hasattr(t, '__setitem__') and hasattr(t, '__delitem__')
它们都是特殊的方法,
\uuuu len\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,和\uuuu setitem\uuuu
和\uuu delitem\uuuu
如您所料。这是一种契约,但客体是否真的这样做取决于客体是否遵守契约
注意上述函数也将返回映射的True
,例如dict
,因为映射也有这些方法。要克服这一点,您可以做更繁重的工作:
但是大多数时候,你不需要这个,只要做你想做的事情,就好像对象是一个序列,如果你愿意,捕获一个异常。这更像是python。我认为下面的代码片段符合您的要求:
def is_sequence(obj):
return hasattr(type(obj), '__iter__')
对于Python3和2.6+,您可以检查它是否是集合的子类
>>> import collections
>>> isinstance(myObject, collections.Sequence)
True
在Python3.7中,必须使用collections.abc.Sequence
(collections.Sequence
将在Python3.8中删除):
但是,这对于实现\uu len\uuuuuuuuuuuuuuuuuuu()
和\uuuuuuu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
的duck类型序列不起作用,但。但它适用于所有内置Python序列类型:列表、元组、字符串等
虽然所有序列都是可iterable,但并非所有的可iterable都是序列(例如,集合和字典都是可iterable,但不是序列)。为完整起见,检查字典和集合的hasattr(type(obj),“\uu iter”
将返回True
。。库中有一个实用工具is_sequence
(“使用Python进行科学计算的基本包”)
但它接受集合作为序列,并拒绝字符串
代码看起来有点像@adrian的(参见),有点不稳定
def is_sequence(seq):
if is_string(seq):
return False
try:
len(seq)
except Exception:
return False
return True
相关:在python中,如何确定变量是否是可写的?是的,但尽管所有序列都是可重用的,但并非所有的可重用都是序列(例如,集合和dict是内置的可重用容器,它们不是序列)。请注意,对于实现sequence协议但不涉及集合的对象,此代码示例将返回错误的结果。sequence
ABC。是的:与更简单的ABC不同,sequence不实现\uuuuuu子类钩子\uuuu
类方法,因此,它永远不会自动识别一个选择不向其注册(或继承)的类——本质上不可能通过内省来判断一个类的\uuu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
是否接受整数和切片,是否在错误的索引上引发索引器,等等——基本上,你需要排除dict
和set
(如果你只是做内省的话,这看起来确实“实现了序列协议”…但结果却不是!-)。集合很容易排除,因为它们没有\uGetItem\uuuuu
,但映射要困难得多。我见过的最好的检查可能是查找键
,就像dict.update
那样,但这仍然有很多地方需要改进。因此,要将我的自定义类型检测为序列,我必须对序列进行子类化?提到的警告的一个很好的例子是numpy数组,具有序列的所有必需属性,但isinstance无法识别这些属性。如果这对numpy数组都不起作用,那就太没希望了。这是一个赋值约束。如果争论
>>> import collections
>>> isinstance(myObject, collections.Sequence)
True
>>> import collections.abc
>>> isinstance(myObject, collections.abc.Sequence)
True
>>> from numpy.distutils.misc_util import is_sequence
>>> is_sequence((2,3,4))
True
>>> is_sequence(45.9)
False
>>> is_sequence(set((1,2)))
True
>>> is_sequence("abc")
False
def is_sequence(seq):
if is_string(seq):
return False
try:
len(seq)
except Exception:
return False
return True