Поскольку Python 2.6, с введением абстрактных базовых классов, isinstance
(используется на ABC, а не в конкретных классах), теперь считается вполне приемлемым. В частности:
from abc import ABCMeta, abstractmethod
class NonStringIterable:
__metaclass__ = ABCMeta
@abstractmethod
def __iter__(self):
while False:
yield None
@classmethod
def __subclasshook__(cls, C):
if cls is NonStringIterable:
if any("__iter__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
Это точная копия (изменение только имя класс) Iterable
, как это определено в _abcoll.py
(деталь реализации collections.py
) ... причина это работает, как вы хотите, в то время как collections.Iterable
не , заключается в том, что последний имеет дополнительную милю, чтобы гарантировать, что строки считаются итерируемыми, вызвав Iterable.register(str)
явно после этого class
.
Конечно, легко добавить __subclasshook__
, возвращая False
до того, как any
вызовет другие классы, которые вы хотите специально исключить из своего определения.
В любом случае, после того, как вы импортировали этот новый модуль как myiter
, isinstance('ciao', myiter.NonStringIterable)
будет False
и isinstance([1,2,3], myiter.NonStringIterable)
будет True
, так же, как вы запрашиваете - и в Python 2.6 и позже это считается надлежащим образом воплотить такие проверяет ... определяет абстрактный базовый класс и проверяет на нем isinstance
.
Какая версия Python? Я считаю, что ответ отличается от 2. * и 3 –
Я использую версию 2.5 – priestc
Вам сказали неправильно, isinstance - неплохая практика. –