Python:检查对象是否是序列

发布于 2024-09-03 20:00:38 字数 87 浏览 7 评论 0原文

在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

神也荒唐 2024-09-10 20:00:38

如果 x 无法迭代,iter(x) 将引发 TypeError - 但该检查“接受”集合和字典,尽管它“拒绝”其他非序列,例如 None 和数字。

另一方面,字符串(大多数应用程序希望将其视为“单个项目”而不是序列)实际上是序列(因此,任何测试,除非针对字符串进行特殊处理,都将确认它们是)。因此,这种简单的检查通常是不够的。

在 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

您会注意到字符串仍然被视为“序列”(因为它们),但至少您得到了字典和集合。如果您想从“存在序列”的概念中排除字符串,您可以使用collections.MutableSequence(但这也排除了元组,元组与字符串一样,是序列,但不可变),或者明确地执行:

import collections

def issequenceforme(obj):
    if isinstance(obj, basestring):
        return False
    return isinstance(obj, collections.Sequence)

调味,趁热享用!-)

PS:对于 Python 3,使用 str 而不是 basestring,对于 Python 3.3+:抽象基类,例如Sequence 已移至 collections.abc

iter(x) will raise a TypeError if x cannot be iterated on -- but that check "accepts" sets and dictionaries, though it "rejects" other non-sequences such as None 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".

>>> 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

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:

import collections

def issequenceforme(obj):
    if isinstance(obj, basestring):
        return False
    return isinstance(obj, collections.Sequence)

Season to taste, and serve hot!-)

PS: For Python 3, use str instead of basestring, and for Python 3.3+: Abstract Base Classes like Sequence have moved to collections.abc.

无言温柔 2024-09-10 20:00:38

对于 Python 3 和 2.6+,您可以检查它是否是 collections.Sequence 的子类:

>>> import collections
>>> isinstance(myObject, collections.Sequence)
True

在 Python 3.7 中,您必须使用 collections.abc.Sequence (collections.Sequence)。 Sequence 将在 Python 3.8 中删除):

>>> import collections.abc
>>> isinstance(myObject, collections.abc.Sequence)
True

但是,这对于实现 __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:

>>> import collections
>>> isinstance(myObject, collections.Sequence)
True

In Python 3.7 you must use collections.abc.Sequence (collections.Sequence will be removed in Python 3.8):

>>> import collections.abc
>>> isinstance(myObject, collections.abc.Sequence)
True

However, this won't work for duck-typed sequences which implement __len__() and __getitem__() but do not (as they should) subclass collections.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 return True for dictionaries and sets.

雪化雨蝶 2024-09-10 20:00:38

由于Python“遵循”鸭子类型,其中一种方法是检查对象是否具有某些成员(方法)。

序列有长度,有项目序列,并且支持切片 [文档]。所以,它会是这样的:

def is_sequence(obj):
    t = type(obj)
    return hasattr(t, '__len__') and hasattr(t, '__getitem__')
    # additionally: and hasattr(t, '__setitem__') and hasattr(t, '__delitem__')

它们都是特殊方法,__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

但是大多数时候你不需要这个,只需做你想做的事情,就好像对象是一个序列一样如果您愿意,可以捕获异常。这更加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:

def is_sequence(obj):
    t = type(obj)
    return hasattr(t, '__len__') and hasattr(t, '__getitem__')
    # additionally: and hasattr(t, '__setitem__') and hasattr(t, '__delitem__')

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:

def is_sequence(obj):
    try:
        len(obj)
        obj[0:0]
        return True
    except TypeError:
        return False

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.

善良天后 2024-09-10 20:00:38

为了完整性。 numpy 库中有一个实用程序 is_sequence (“使用 Python 进行科学计算的基础包” )。

>>> 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

代码看起来有点像@adrian的(参见numpy git 代码),有点不稳定。

def is_sequence(seq):
    if is_string(seq):
        return False
    try:
        len(seq)
    except Exception:
        return False
    return True

For the sake of completeness. There is a utility is_sequence in numpy library ("The fundamental package for scientific computing with Python").

>>> from numpy.distutils.misc_util import is_sequence
>>> is_sequence((2,3,4))
True
>>> is_sequence(45.9)
False

But it accepts sets as sequences and rejects strings

>>> is_sequence(set((1,2)))
True
>>> is_sequence("abc")
False

The code looks a bit like @adrian 's (See numpy git code), which is kind of shaky.

def is_sequence(seq):
    if is_string(seq):
        return False
    try:
        len(seq)
    except Exception:
        return False
    return True
扛起拖把扫天下 2024-09-10 20:00:38

Python 2.6.5 文档 描述了以下序列类型:字符串、Unicode 字符串、列表、元组、缓冲区和 xrange。

def isSequence(obj):
    return type(obj) in [str, unicode, list, tuple, buffer, xrange]

The Python 2.6.5 documentation describes the following sequence types: string, Unicode string, list, tuple, buffer, and xrange.

def isSequence(obj):
    return type(obj) in [str, unicode, list, tuple, buffer, xrange]
圈圈圆圆圈圈 2024-09-10 20:00:38

为什么要问为什么

尝试获取长度并且如果异常返回 false

def haslength(seq):
    try:
        len(seq)
    except:
        return False
    return True

why ask why

try getting a length and if exception return false

def haslength(seq):
    try:
        len(seq)
    except:
        return False
    return True
浮光之海 2024-09-10 20:00:38

你为什么要这样做?这里的正常方法是需要某种类型的东西(序列或数字或类似文件的对象等),然后使用它而不检查任何内容。在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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文