Проверка типов: итеративный тип, который не является строкой
Чтобы лучше объяснить, рассмотрим эту простую функцию проверки типов:
from collections import Iterable
def typecheck(obj):
return not isinstance(obj, str) and isinstance(obj, Iterable)
Если obj
является итерируемым типом, отличным от str
, он возвращает True
. Однако, если obj
является str
или неистребимым типом, он возвращает False
.
Есть ли способ более эффективно выполнять проверку типа? Я имею в виду, кажется, что избыточно проверять тип obj
один раз, чтобы увидеть, не является ли это str
, а затем снова проверить его, чтобы увидеть, является ли он итерируемым.
Я думал о перечислении любого другого итерируемого типа, кроме str
, как это:
return isinstance(obj, (list, tuple, dict,...))
Но проблема в том, что этот подход пропустит любые другие повторяющиеся типы, которые явно не указаны.
Итак... есть ли что-нибудь лучше или это подход, который я дал в функции наиболее эффективным?
Ответы
Ответ 1
В python 2.x проверка атрибута __iter__
была полезной (хотя и не всегда мудрой), потому что iterables должен иметь этот атрибут, но строки этого не сделали.
def typecheck(obj): return hasattr(myObj, '__iter__')
Нижняя сторона заключалась в том, что __iter__
не был действительно путинским способом: некоторые объекты могут реализовать __getitem__
, но не __iter__
например.
В Python 3.x строки получили атрибут __iter__
, нарушив этот метод.
Метод, который вы указали, является наиболее эффективным, действительно Pythonic способом, который я знаю в Python 3.x:
def typecheck(obj): return not isinstance(obj, str) and isinstance(obj, Iterable)
Существует гораздо более быстрый (более эффективный) способ проверки __iter__
как в Python 2.x, а затем проверки str
.
def typecheck(obj): return hasattr(obj, '__iter__') and not isinstance(obj, str)
Это имеет ту же оговорку, что и в Python 2.x, но намного быстрее.
Ответ 2
Я проверяю его с помощью этого кода, и он отлично работает с Python 2 и 3
from __future__ import unicode_literals
import types
import collections
var = ["a", "b", "c"]
if isinstance(var, collections.Iterable) and \
not isinstance(var, types.StringTypes):
return var