nic*_*ine 58 python if-statement sequences sequence
在python中有一个简单的方法来判断某些东西是不是一个序列?我试着这么做:
if x is not sequence
但是python并不喜欢这样
Ale*_*lli 67
iter(x)
将提出一个TypeError
if x
不能迭代 - 但该检查"接受"集和字典,虽然它"拒绝"其他非序列,如None
和数字.
另一方面手,字符串(其中大多数应用需要考虑"单品",而不是序列)是实际上序列(因此,任何测试,除非specialcased的字符串,是要确认它们).因此,这种简单的检查通常是不够的.
在Python 2.6及更高版本中,引入了抽象基类,并且在其他强大功能中,它们为这种"类别检查"提供了更好的系统支持.
>>> import collections
>>> isinstance([], collections.Sequence)
True
>>> isinstance((), collections.Sequence)
True
>>> isinstance(23, collections.Sequence)
False
>>> isinstance('foo', collections.Sequence)
True
>>> isinstance({}, collections.Sequence)
False
>>> isinstance(set(), collections.Sequence)
False
Run Code Online (Sandbox Code Playgroud)
你会注意到字符串仍然被认为是"一个序列"(因为它们是),但至少你得到了dicts和set.如果你想从你的"正在序列"的概念中排除字符串,你可以使用collections.MutableSequence
(但这也排除了元组,像字符串一样,是序列,但不是可变的),或者明确地做:
import collections
def issequenceforme(obj):
if isinstance(obj, basestring):
return False
return isinstance(obj, collections.Sequence)
Run Code Online (Sandbox Code Playgroud)
品尝季节,热腾腾! - )
我认为以下代码片段可以满足您的需求:
def is_sequence(obj):
return hasattr(type(obj), '__iter__')
Run Code Online (Sandbox Code Playgroud)
对于 Python 3 和 2.6+,您可以检查它是否是以下的子类collections.Sequence
:
>>> import collections
>>> isinstance(myObject, collections.Sequence)
True
Run Code Online (Sandbox Code Playgroud)
在 Python 3.7 中,您必须使用collections.abc.Sequence
(collections.Sequence
将在 Python 3.8 中删除):
>>> import collections.abc
>>> isinstance(myObject, collections.abc.Sequence)
True
Run Code Online (Sandbox Code Playgroud)
然而,这对于其实现鸭类型的序列将无法正常工作__len__()
和__getitem__()
,但不会(因为他们应该)的子类collections.Sequence
。但它适用于所有内置的 Python 序列类型:列表、元组、字符串等。
虽然所有序列都是可迭代的,但并非所有可迭代的都是序列(例如,集合和字典是可迭代的,但不是序列)。检查hasattr(type(obj), '__iter__')
将返回True
字典和集合。
由于Python"坚持"鸭子类型,其中一种方法是检查对象是否有某个成员(方法).
序列具有长度,具有项目序列,并且支持切片[ doc ].所以,它会是这样的:
def is_sequence(obj):
t = type(obj)
return hasattr(t, '__len__') and hasattr(t, '__getitem__')
# additionally: and hasattr(t, '__setitem__') and hasattr(t, '__delitem__')
Run Code Online (Sandbox Code Playgroud)
它们都是特殊的方法,__len__()
应该返回项目的数量,__getitem__(i)
应该返回一个项目(按顺序它是第i个项目,但不是映射),__getitem__(slice(start, stop, step))
应该返回子序列,__setitem__
并且__delitem__
像你期望的那样.这是一个合同,但对象是否真的这样做取决于对象是否遵守合同.
注意,上面的函数也将返回True
映射,例如dict
,因为映射也具有这些方法.为了克服这个问题,你可以做更重的工作:
def is_sequence(obj):
try:
len(obj)
obj[0:0]
return True
except TypeError:
return False
Run Code Online (Sandbox Code Playgroud)
但是大多数时候你不需要这个,只要做你想要的就好,就像对象是一个序列一样,如果你愿意,也可以捕获异常.这更像是pythonic.
在Python的2.6.5文档介绍以下序列类型:字符串,Unicode字符串,列表,元组,缓冲,还有range.
def isSequence(obj):
return type(obj) in [str, unicode, list, tuple, buffer, xrange]
Run Code Online (Sandbox Code Playgroud)
为了完整性。numpyis_sequence
库中有一个实用程序(“Python 科学计算的基础包”)。
>>> from numpy.distutils.misc_util import is_sequence
>>> is_sequence((2,3,4))
True
>>> is_sequence(45.9)
False
Run Code Online (Sandbox Code Playgroud)
但它接受集合作为序列并拒绝字符串
>>> is_sequence(set((1,2)))
True
>>> is_sequence("abc")
False
Run Code Online (Sandbox Code Playgroud)
该代码看起来有点像 @adrian 的(请参阅numpy git code),有点不稳定。
def is_sequence(seq):
if is_string(seq):
return False
try:
len(seq)
except Exception:
return False
return True
Run Code Online (Sandbox Code Playgroud)