Python: проверить, является ли объект последовательностью - PullRequest
55 голосов
/ 30 мая 2010

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

Ответы [ 7 ]

65 голосов
/ 30 мая 2010

iter(x) повысит TypeError, если x не может быть повторен, но эта проверка «принимает» наборы и словари, хотя она «отклоняет» другие непоследовательности, такие как 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)

Приправить по вкусу и подавать горячим! -)

9 голосов
/ 24 июля 2016

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

def is_sequence(obj):
    return hasattr(type(obj), '__iter__')
6 голосов
/ 25 июня 2015

Поскольку 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 -й элемент, , но не с mapping), __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

Но в большинстве случаев вам это не нужно, просто делайте что хотите, как если бы объект представлял собой последовательность, и перехватывайте исключение, если хотите. Это более питонический.

5 голосов
/ 30 мая 2010

Документация Python 2.6.5 описывает следующие типы последовательностей: строка, строка Unicode, список, кортеж, буфер и xrange.

def isSequence(obj):
    return type(obj) in [str, unicode, list, tuple, buffer, xrange]
0 голосов
/ 10 февраля 2019

Для Python 3 и 2.6+ вы можете проверить, является ли это подклассом collections.Sequence:

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

В Python 3.7 вы должны использовать collections.abc.Sequence (collections.Sequence будет удалено в Python 3.8):

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

Однако, это не будет работать для последовательностей типа «утка», которые реализуют __len__() и __getitem__(), но не (как они должны) подкласс collections.Sequence. Но это будет работать для всех встроенных типов последовательностей Python: списков, кортежей, строк и т. Д.

Хотя все последовательности являются итеративными, не все итерируемые являются последовательностями (например, наборы и словари являются итеративными, но не последовательностями). Проверка hasattr(type(obj), '__iter__') вернет True для словарей и наборов.

0 голосов
/ 26 августа 2012

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

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

def haslength(seq):
    try:
        len(seq)
    except:
        return False
    return True
0 голосов
/ 30 мая 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...