В Python, что состоит в том, чтобы протестировать лучший способ, если переменная содержит список или кортеж? (т.е. набор)
isinstance()
столь злой, как предложенный здесь? http://www.canonical.org/~kragen/isinstance/
Обновление: наиболее распространенная причина я хочу отличить список от строки, состоит в том, когда у меня есть некоторое неограниченно долго глубокое вложенное дерево / структура данных списков списков списков строк и т.д., которые я исследую с рекурсивным алгоритмом, и я должен знать, когда я поразил "листовые" узлы.
Продолжайте использовать isinstance
, если вам это нужно. Это в некоторой степени зло, поскольку исключает пользовательские последовательности, итераторы и другие вещи, которые могут вам действительно понадобиться. Однако иногда нужно вести себя по-другому, если кто-то, например, передает строку. Я бы предпочел явную проверку на str
или unicode
, например, так:
import types
isinstance(var, types.StringTypes)
N.B. Не путайте types.StringType
с types.StringTypes
. Последний включает в себя объекты str
и unicode
.
Модуль types
многие считают устаревшим в пользу проверки непосредственно типа объекта, поэтому, если вы не хотите использовать вышеупомянутый модуль, вы можете альтернативно проверить явным образом str
и unicode
, например, так:
isinstance(var, (str, unicode)):
Редактировать:
Еще лучше:
isinstance(var, basestring)
Конец редактирования
После любого из этих вариантов можно вернуться к поведению, как будто вы получаете нормальную последовательность, позволяя непоследовательностям вызывать соответствующие исключения.
Видите ли, "зло" в проверке типов не в том, что вы можете захотеть вести себя по-другому для определенного типа объектов, а в том, что вы искусственно ограничиваете свою функцию от правильных действий с неожиданными типами объектов, которые в противном случае делали бы правильные вещи. Если у вас есть конечный fallback, который не проверяется на тип, вы снимаете это ограничение. Следует отметить, что слишком большая проверка типов - это запах кода, который указывает на то, что вам, возможно, следует провести рефакторинг, но это не означает, что вы должны избегать ее с самого начала.
Нет ничего плохого в использовании Isinstance
, пока он не является избыточным. Если переменная должна быть только списком / кортеж, затем документируйте интерфейс и просто используйте его как таковые. В противном случае чек совершенно разумный:
if isinstance(a, collections.Iterable):
# use as a container
else:
# not a container!
Этот тип проверки имеет несколько хороших случаев использования, такие как со стандартной строкой StartSwith / Эндонсвит методы (хотя для того, чтобы быть точным Реализуются в C в CPYPHON, используя явную проверку, чтобы увидеть, если это кортеж - есть более одного способа решения этой проблемы, как указано в статье, которую вы ссылаетесь).
Явная проверка часто лучше, чем пытаться использовать объект в качестве контейнера и обрабатывать исключение - это может привести к тому, что всевозможные проблемы с кодом запускаются частично или без необходимости.
Документируйте аргумент по мере необходимости последовательности и использовать его как последовательность. Не проверяйте тип.
Если вам просто нужно знать, можно ли использовать нотацию foo [123]
с переменной, вы можете проверить наличие атрибута __ getitem __
(который вызывает Python при доступе по индексу) с помощью hasattr (foo, '__getitem __')
Python использует «набрать уток», то есть, если переменная кваки, как утка, она должна быть уткой. В вашем случае вы, вероятно, хотите, чтобы это было иначебно, или вы хотите получить доступ к пункту в определенном индексе. Вы должны просто сделать это: т. Е. Используйте объект в для var:
или VAR [IDX]
Внутри Попробуйте
блок, и если вы получите исключение, это разве «Утка ...
В принципе, я согласен с Игнасио выше, но вы также можете использовать тип , чтобы проверить, не является ли что-то кортежом или списком.
>>> a = (1,)
>>> type(a)
(type 'tuple')
>>> a = [1]
>>> type(a)
(type 'list')