Python: проверьте, является ли объект последовательностью

В python есть простой способ сказать, что что-то не является последовательностью? Я пытался просто сделать: if x is not sequence, но python не понравилось

Ответ 1

iter(x) будет поднимать TypeError, если x не может быть повторен, но это проверяет "принимает" наборы и словари, хотя оно "отвергает" другие непоследовательности, такие как None и numbers.

С другой стороны, строки (которые большинство приложений хотят рассматривать "отдельные элементы", а не последовательности) на самом деле являются последовательностями (поэтому любой тест, если специально не используется для строк, собирается подтвердить, что они есть). Таким образом, таких простых проверок часто недостаточно.

В 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

Вы заметите, что строки по-прежнему считаются "последовательностью" (с тех пор как они), но по крайней мере вы получаете dicts и укладываете в сторону. Если вы хотите исключить строки из своей концепции "быть последовательностями", вы можете использовать collections.MutableSequence (но это также исключает кортежи, которые, подобно строкам, являются последовательностями, но не изменяемы) или делают это явно:

import collections

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

Сезон по вкусу и подача горячей! -)

Ответ 2

Документация Python 2.6.5 описывает следующие типы последовательностей: string, Unicode string, list, tuple, buffer и xrange.

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

Ответ 3

Зачем ты это делаешь? Обычный способ здесь - потребовать определенный тип вещи (последовательность или число или файл-подобный объект и т.д.), А затем использовать его, не проверяя ничего. В Python мы обычно не используем классы для переноса семантической информации, но просто используем определенные методы (это называется "утиная печать" ). Мы также предпочитаем API, где мы точно знаем, чего ожидать; использовать аргументы ключевого слова, выполнить предварительную обработку или определить другую функцию, если вы хотите изменить способ работы функции.

Ответ 4

Так как 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__')

Это все специальные методы, __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.

Ответ 5

Я думаю, что приведенный ниже фрагмент кода делает то, что вы хотите:

def is_sequence(obj):
    return hasattr(type(obj), '__iter__')

Ответ 6

зачем спрашивать, почему

попробуйте получить длину, и если исключение вернет false

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