Проверьте, является ли переменная списком или кортежем
В 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