Python:检查对象是否是序列
在 python 中,有没有一种简单的方法来判断某些东西是否不是序列?我尝试这样做: 如果 x 不是序列
但 python 不喜欢这样
In python is there an easy way to tell if something is not a sequence? I tried to just do:if x is not sequence
but python did not like that
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果
x
无法迭代,iter(x)
将引发TypeError
- 但该检查“接受”集合和字典,尽管它“拒绝”其他非序列,例如None
和数字。另一方面,字符串(大多数应用程序希望将其视为“单个项目”而不是序列)实际上是序列(因此,任何测试,除非针对字符串进行特殊处理,都将确认它们是)。因此,这种简单的检查通常是不够的。
在 Python 2.6 及更高版本中,引入了抽象基类,除其他强大功能外,它们还为此类“类别检查”提供了更好、更系统的支持。
您会注意到字符串仍然被视为“序列”(因为它们是),但至少您得到了字典和集合。如果您想从“存在序列”的概念中排除字符串,您可以使用
collections.MutableSequence
(但这也排除了元组,元组与字符串一样,是序列,但不可变),或者明确地执行:调味,趁热享用!-)
PS:对于 Python 3,使用
str
而不是basestring
,对于 Python 3.3+:抽象基类,例如Sequence
已移至collections.abc
。iter(x)
will raise aTypeError
ifx
cannot be iterated on -- but that check "accepts" sets and dictionaries, though it "rejects" other non-sequences such asNone
and numbers.On the other hands, strings (which most applications want to consider "single items" rather than sequences) are in fact sequences (so, any test, unless specialcased for strings, is going to confirm that they are). So, such simple checks are often not sufficient.
In Python 2.6 and better, abstract base classes were introduced, and among other powerful features they offer more good, systematic support for such "category checking".
You'll note strings are still considered "a sequence" (since they are), but at least you get dicts and sets out of the way. If you want to exclude strings from your concept of "being sequences", you could use
collections.MutableSequence
(but that also excludes tuples, which, like strings, are sequences, but are not mutable), or do it explicitly:Season to taste, and serve hot!-)
PS: For Python 3, use
str
instead ofbasestring
, and for Python 3.3+: Abstract Base Classes likeSequence
have moved tocollections.abc
.对于 Python 3 和 2.6+,您可以检查它是否是
collections.Sequence
的子类:在 Python 3.7 中,您必须使用
collections.abc.Sequence
(collections.Sequence)。 Sequence
将在 Python 3.8 中删除):但是,这对于实现
__len__()
和__getitem__()
但执行的鸭子类型序列不起作用不是(正如他们应该的那样)子类collections.Sequence
。但它适用于所有内置的 Python 序列类型:列表、元组、字符串等。虽然所有序列都是可迭代的,但并非所有可迭代都是序列(例如,集合和字典是可迭代的,但不是序列)。检查
hasattr(type(obj), '__iter__')
将为字典和集合返回True
。For Python 3 and 2.6+, you can check if it's a subclass of
collections.Sequence
:In Python 3.7 you must use
collections.abc.Sequence
(collections.Sequence
will be removed in Python 3.8):However, this won't work for duck-typed sequences which implement
__len__()
and__getitem__()
but do not (as they should) subclasscollections.Sequence
. But it will work for all the built-in Python sequence types: lists, tuples, strings, etc.While all sequences are iterables, not all iterables are sequences (for example, sets and dictionaries are iterable but not sequences). Checking
hasattr(type(obj), '__iter__')
will returnTrue
for dictionaries and sets.由于Python“遵循”鸭子类型,其中一种方法是检查对象是否具有某些成员(方法)。
序列有长度,有项目序列,并且支持切片 [文档]。所以,它会是这样的:
它们都是特殊方法,
__len__()
应该返回项目的数量,__getitem__(i)
应该返回一个项目(按顺序是i第一项,但不使用映射),__getitem__(slice(start, stop, step))
应返回子序列,并且__setitem__
和__delitem__
正如您所期望的。这就是这样一个契约,但对象是否真正做到这些,取决于对象是否遵守契约。注意,上面的函数对于映射也会返回
True
,例如dict
,因为映射也有这些方法。为了克服这个问题,你可以做一个更重的工作:但是大多数时候你不需要这个,只需做你想做的事情,就好像对象是一个序列一样如果您愿意,可以捕获异常。这更加Pythonic。
Since Python "adheres" duck typing, one of the approach is to check if an object has some member (method).
A sequence has length, has sequence of items, and support slicing [doc]. So, it would be like this:
They are all special methods,
__len__()
should return number of items,__getitem__(i)
should return an item (in sequence it is i-th item, but not with mapping),__getitem__(slice(start, stop, step))
should return subsequence, and__setitem__
and__delitem__
like you expect. This is such a contract, but whether the object really do these or not depends on whether the object adheres the contract or not.Note that, the function above will also return
True
for mapping, e.g.dict
, since mapping also has these methods. To overcome this, you can do a heavier work:But most of the time you don't need this, just do what you want as if the object is a sequence and catch an exception if you wish. This is more pythonic.
为了完整性。 numpy 库中有一个实用程序
is_sequence
(“使用 Python 进行科学计算的基础包” )。但它接受集合作为序列并拒绝字符串
代码看起来有点像@adrian的(参见numpy git 代码),有点不稳定。
For the sake of completeness. There is a utility
is_sequence
in numpy library ("The fundamental package for scientific computing with Python").But it accepts sets as sequences and rejects strings
The code looks a bit like @adrian 's (See numpy git code), which is kind of shaky.
Python 2.6.5 文档 描述了以下序列类型:字符串、Unicode 字符串、列表、元组、缓冲区和 xrange。
The Python 2.6.5 documentation describes the following sequence types: string, Unicode string, list, tuple, buffer, and xrange.
为什么要问为什么
尝试获取长度并且如果异常返回 false
why ask why
try getting a length and if exception return false
你为什么要这样做?这里的正常方法是需要某种类型的东西(序列或数字或类似文件的对象等),然后使用它而不检查任何内容。在Python中,我们通常不使用类来携带语义信息,而是简单地使用定义的方法(这称为“鸭子类型”)。我们也更喜欢那些我们确切知道期望什么的 API;如果您想更改函数的工作方式,请使用关键字参数、预处理或定义另一个函数。
Why are you doing this? The normal way here is to require a certain type of thing (A sequence or a number or a file-like object, etc.) and then use it without checking anything. In Python, we don't typically use classes to carry semantic information but simply use the methods defined (this is called "duck typing"). We also prefer APIs where we know exactly what to expect; use keyword arguments, preprocessing, or defining another function if you want to change how a function works.