Как я могу определить, имеет ли структура в Python порядок?

Я пишу набор тестовых примеров для пользователей, новых для Python. Одна из проблем, которые я заметил с моими испытаниями, заключается в том, что можно получить ложные срабатывания. Возможно, им повезло и случилось, чтобы каждый элемент был в правильном порядке, однако они действительно должны использовать упорядоченную структуру.

Пока это лучшее решение, которое я мог бы придумать.

self.assertTrue(isinstance(result, Sequence) or
                isinstance(result, GeneratorType) or
                callable(getattr(result, '__reversed__', False)))

Однако я не уверен, что GeneratorType действительно заказан или этот тест является исчерпывающим. Я чувствую, что должен быть лучший способ проверить это. Как проверить, что структура имеет порядок?

Ответ 1

Я думаю, это очень интересно. В чистом питоне нет (без кода полезности) чтобы проверить, упорядочена ли коллекция.

Пусть идут последовательно =)

Чтобы проверить Sequence или GeneratorType вы можете использовать тип collections.Iterable.

>>>
>>> import collections
>>>
>>> result = [1,2,3,4,-1]
>>> isinstance(result, collections.Iterable)
True
>>>
>>> def generator_func(arg=10):
...     for i in xrange(arg):
...         yield i
...
>>>
>>> generator_func()
<generator object generator_func at 0x7f667c50f190>
>>>
>>> result = generator_func()
>>> isinstance(result, collections.Iterable)
True

Но:

>>>
>>> result = {1,2,3,4,-1}
>>> isinstance(result, collections.Iterable)
True
>>>

Это плохо для вас. Потому что:

>>> x = {1,2,3,-1}
>>> x
set([1, 2, 3, -1])
>>> [_ for _ in x]
[1, 2, 3, -1]
>>> x = {1,2,3,0}
>>> x
set([0, 1, 2, 3])
>>> [_ for _ in x]
[0, 1, 2, 3]
>>> import collections
>>> isinstance(x, collections.Iterable)
True
>>>

Конечно, для этого случая вы должны использовать коллекции. Только степень.

>>> result = {1,2,3,4,-1}
>>> isinstance(result, collections.Sequence)
False
>>> isinstance({1:2, 3:3}, collections.Sequence)
False
>>>

Но:

>>> result = generator_func()
>>> isinstance(result, collections.Sequence)
False
>>> 

Таким образом, я думаю, что идея проверить Sequence or GeneratorType хороша. Проверьте эту ссылку:

Итак:

>>> result = generator_func()
>>> isinstance(result, (collections.Sequence, collections.Iterator))
True
>>> result = [1,2,3,4,5]
>>> isinstance(result, (collections.Sequence, collections.Iterator))
True
>>> result = (1,2,3,4,5)
>>> isinstance(result, (collections.Sequence, collections.Iterator))
True
>>> result = {1,2,3,4,5}
>>> isinstance(result, (collections.Sequence, collections.Iterator))
False
>>> result = {1:1,2:2,3:3,4:4,5:5}
>>> isinstance(result, (collections.Sequence, collections.Iterator))
False
>>> 

По заказу.

Если вы не уверены в порядке вещей, Я думаю, вы должны проверить их явно.

"Явный лучше, чем неявный."

>>>
>>> def order_check(result, order_rule = cmp_rule):
...     for item, next_item in zip(result, result[1:]):
...         if not order_rule(item, next_item):
...             return False
...     return True
...
>>> def cmp_rule(item, next_item):
...     if item < next_item:
...         return True
...     return False
...
>>>
>>> result = [1,2,3,4,5]
>>> order_check(result)
True
>>> result = [1,2,3,4,5,-1]
>>> order_check(result)
False
>>>

Но, честно говоря, генераторы гарантируют что порядок будет таким же, как вы его генерируете.

Ответ 2

Вы не полностью описали, что вы подразумеваете под свойством "порядок"; ваша "вызываемая" - хорошая идея. Я предлагаю вам прочитать методы "dunder" (двойные подчеркивания), чтобы увидеть, соответствует ли одно из них определению, которое вы хотите. Из того, что вы нам дали, я сильно подозреваю, что __getitem__ - это то, что вы хотите. Существует также метод "попросить прощения" установки блока try-except в структуре:

try:
    dummy = (_ for _ in result)
    has_order = True
except:
    has_order = False
return has_order