Проверьте, является ли переменная списком или кортежем

В Python, что лучший способ проверить, если переменная содержит список или кортеж? (т.е. коллекция)

Является ли isinstance() таким же злым, как предлагается здесь? http://www.canonical.org/~kragen/isinstance/

Обновление: наиболее распространенная причина, по которой я хочу отличить список от строки, это когда у меня есть какое-то неопределенно глубокое вложенное дерево/структура данных списков списков строк и т.д., Которые я изучаю с помощью рекурсивного алгоритма, и мне нужно чтобы знать, когда я ударил "лист" узлы.

Ответ 1

Идем дальше и используем isinstance, если вам это нужно. Это несколько злой, поскольку он исключает пользовательские последовательности, итераторы и другие вещи, которые вам действительно понадобятся. Однако иногда вам нужно вести себя по-другому, если кто-то, например, передает строку. Мое предпочтение было бы явно проверять на str или unicode так:

import types
isinstance(var, types.StringTypes)

N.B. Не принимайте types.StringType за types.StringTypes. Последний включает объекты str и unicode.

Модуль types считается многими устаревшими в пользу просто проверки непосредственно против типа объекта, поэтому, если вы предпочитаете не использовать вышеизложенное, вы можете альтернативно явно проверять на str и unicode, вот так:

isinstance(var, (str, unicode)):

Edit:

Еще лучше:

isinstance(var, basestring)

Редактирование конца

После любого из них вы можете вернуться к тому, чтобы вести себя так, как будто вы получаете нормальную последовательность, позволяя не-последовательностям поднимать соответствующие исключения.

Посмотрите на то, что "зло" в отношении проверки типов не означает, что вы можете вести себя по-другому для определенного типа объекта, это то, что вы искусственно ограничиваете свою функцию от правильной работы с помощью неожиданных типов объектов, которые в противном случае правильная вещь. Если у вас есть окончательный резерв, который не проверяется типом, вы удаляете это ограничение. Следует отметить, что слишком большая проверка типов - это запах кода, который указывает, что вы можете захотеть сделать какой-то рефакторинг, но это не обязательно означает, что вы должны избегать этого из getgo.

Ответ 2

if type(x) is list:
    print 'a list'
elif type(x) is tuple:
    print 'a tuple'
else:
    print 'neither a tuple or a list'

Ответ 3

Нет ничего плохого в использовании isinstance, если он не является избыточным. Если переменная должна быть только списком/кортежем, тогда документируйте интерфейс и просто используйте его как таковой. В противном случае проверка вполне разумна:

if isinstance(a, collections.Iterable):
    # use as a container
else:
    # not a container!

Этот тип проверки имеет некоторые хорошие варианты использования, например, со стандартной строкой startswith/endswith (хотя они точны, они реализованы на C в CPython, используя явную проверку, чтобы увидеть, является ли он кортежем - там более одного способа решить эту проблему, как указано в статье, на которую вы ссылаетесь).

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

Ответ 4

Документируйте аргумент как необходимый для последовательности и используйте его как последовательность. Не проверяйте тип.

Ответ 5

Как насчет: hasattr(a, "__iter__")?

Он сообщает, может ли возвращенный объект быть итерирован как генератор. По умолчанию кортежи и списки могут, но не типы строк.

Ответ 6

В Python 2.8 type(list) is list возвращается false
Я бы предложил сравнить этот тип этим ужасным способом:

if type(a) == type([]) :
  print "variable a is a list"

(ну, по крайней мере, на моей системе, используя anaconda на Mac OS X Yosemite)

Ответ 7

Python использует "Duck typing", т.е. если переменная kwaks, как утка, она должна быть утиной. В вашем случае вы, вероятно, хотите, чтобы он был итерируемым, или вы хотите получить доступ к элементу по определенному индексу. Вы должны просто сделать это: используйте объект в for var: или var[idx] внутри блока try, и если вы получите исключение, это не утка...

Ответ 8

>>> l = []
>>> l.__class__.__name__ in ('list', 'tuple')
True

Ответ 9

Если вам просто нужно знать, можете ли вы использовать нотацию foo[123] с переменной, вы можете проверить наличие атрибута __getitem__ (который вызывает вызовы python при доступе по индексу) с помощью hasattr(foo, '__getitem__')

Ответ 10

В принципе, я согласен с Ignacio выше, но вы также можете использовать тип, чтобы проверить, есть ли что-то в кортеже или списке.

>>> a = (1,)
>>> type(a)
(type 'tuple')
>>> a = [1]
>>> type(a)
(type 'list')

Ответ 11

Должен быть более сложный тест, если вы действительно хотите обрабатывать практически что-либо как аргумент функции.

type(a) != type('') and hasattr(a, "__iter__")

Хотя, как правило, достаточно просто указать, что функция ожидает итерации, а затем проверяет только type(a) != type('').

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

Ответ 12

Другой простой способ выяснить, является ли переменная списком или кортежем или вообще проверить тип переменной:

    def islist(obj):

        if ("list" in str(type(obj)) ): return True

        else : return False