Истинная или False версия, основанная на ответе @DMfll:
try:
# python2
from urlparse import urlparse
except:
# python3
from urllib.parse import urlparse
a = 'http://www.cwi.nl:80/%7Eguido/Python.html'
b = '/data/Python.html'
c = 532
d = u'dkakasdkjdjakdjadjfalskdjfalk'
def uri_validator(x):
try:
result = urlparse(x)
return result.scheme and result.netloc and result.path
except:
return False
print(uri_validator(a))
print(uri_validator(b))
print(uri_validator(c))
print(uri_validator(d))
Дает:
True
True
False
True
Проверка на __iter__
работает на типах последовательностей, но не работает, например, на строках на Python 2. Хотелось бы знать и правильный ответ, до тех пор есть одна возможность (которая работала бы и на строках):
попробуйте:
some_object_iterator = iter(some_object)
за исключением TypeError как te:
распечатать some_object, 'is not iterable'.
Встроенный итер
проверяет метод __iter__
или, в случае строк, метод __getitem__
.
Другой общий питонический подход заключается в том, чтобы считать итерабельным, а затем грациозно провалиться, если он не работает на данном объекте. Глоссарий Python:
Питонический стиль программирования, который определяет тип объекта, изучая его метод или атрибутную сигнатуру, а не явное отношение к какому-либо типу объекта ("Если он выглядит как утка и крякает как утка, то это должна быть утка"). Подчеркивая интерфейсы, а не конкретные типы, хорошо продуманный код повышает его гибкость, позволяя полиморфное замещение. Duck-типирование позволяет избежать использования тестов с помощью type() или isinstance(). Вместо этого обычно используется стиль программирования EAFP (Easier to Ask Forgiveness than Permission).
...
try: _ = (e для e в моем_объекте) кроме TypeError: распечатать my_object, 'is not iterable'.
Модуль Collections
предоставляет некоторые абстрактные базовые классы, которые позволяют спрашивать у классов или экземпляров, предоставляют ли они определенную функциональность, например:
из collection.abc import Iterable
если это возможно:
# e is iterable
Однако это не проверяет на наличие классов, которые являются итерабельными через __getitem__
.
В Python <= 2.5 вы не можете и не должны - итеративный интерфейс был «неформальным».
Но, начиная с Python 2.6 и 3.0, вы можете использовать новый ABC (абстрактный базового класса) вместе с некоторыми встроенными ABC, которые доступны в модуле коллекций:
from collections import Iterable
class MyObject(object):
pass
mo = MyObject()
print isinstance(mo, Iterable)
Iterable.register(MyObject)
print isinstance(mo, Iterable)
print isinstance("abc", Iterable)
Теперь, желательно это или действительно работает, это просто вопрос соглашений. Как видите, вы можете зарегистрировать не повторяемый объект как Iterable - и это вызовет исключение во время выполнения. Следовательно, isinstance приобретает «новое» значение - он просто проверяет совместимость «объявленных» типов, что является хорошим вариантом для Python.
С другой стороны, если ваш объект не удовлетворяет нужному интерфейсу, что ты собираешься делать? Возьмем следующий пример:
from collections import Iterable
from traceback import print_exc
def check_and_raise(x):
if not isinstance(x, Iterable):
raise TypeError, "%s is not iterable" % x
else:
for i in x:
print i
def just_iter(x):
for i in x:
print i
class NotIterable(object):
pass
if __name__ == "__main__":
try:
check_and_raise(5)
except:
print_exc()
print
try:
just_iter(5)
except:
print_exc()
print
try:
Iterable.register(NotIterable)
ni = NotIterable()
check_and_raise(ni)
except:
print_exc()
print
Если объект не ' Чтобы удовлетворить ваши ожидания, вы просто выдаете ошибку TypeError, но если правильный ABC был зарегистрирован, ваша проверка бесполезна. Напротив, если доступен метод __ iter __
, Python автоматически распознает объект этого класса как Iterable.
Итак, если вы просто ожидаете итерацию, переберите ее и забудьте. С другой стороны, если вам нужно делать разные вещи в зависимости от типа ввода, вы можете найти инфраструктуру ABC очень полезной.
Я нашел хорошее решение здесь:
isiterable = lambda obj: isinstance(obj, basestring) \
or getattr(obj, '__iter__', False)
Можно попробовать так:
def iterable(a):
try:
(x for x in a)
return True
except TypeError:
return False
Если мы можем сделать генератор, который итератует над ним (но никогда не используйте генератор, чтобы он не занимал много места), то он итерабельный. Похоже на "ду". Зачем вообще определять, является ли переменная итерабельной?
.try:
#treat object as iterable
except TypeError, e:
#object is not actually iterable
Не проводите проверку, чтобы увидеть , действительно ли ваша утка , чтобы понять, является ли она пригодной для употребления или нет, обращайтесь с ней так, как если бы это было так, и жалуйтесь, если это не так
Этого недостаточно: объект, возвращаемый __iter__
, должен реализовать протокол итерации (т.е. следующий
метод). См. соответствующий раздел в документации .
На языке Python хорошая практика - "попробовать и посмотреть" вместо "проверить".
.try:
iterator = iter(theElement)
except TypeError:
# not iterable
else:
# iterable
# for obj in iterator:
# pass
Используйте Абстрактные базовые классы . Им нужна как минимум Python 2.6 и они работают только для классов нового стиля.
from collections.abc import Iterable # import directly from collections for Python < 3.3
if isinstance(theElement, Iterable):
# iterable
else:
# not iterable
Однако, iter()
немного надежнее, как описано в документации:
Проверка
isinstance(obj, Iterable)
обнаруживает классы, которые являются зарегистрированные как Iterable или имеющие метод__iter__()
, но он не обнаруживает классы, которые итератируют с помощью__getitem__()
. метод. Единственный надежный способ определить, является ли объект возможно ли вызватьiter(obj)
.