5

I would like to check if a collection that has been passed to a function is ordered, that is, the order of elements is fixed. (I am not talking about "sorted".)

  • A set is not ordered.
  • lists and tuples are ordered.

Is there a generic test that I can use?

bers
  • 4,817
  • 2
  • 40
  • 59

1 Answers1

6

Ordered non-mapping collections typically implement the sequence protocol (which is mainly characterized by providing indexed access via a __getitem__ method) and can be type-tested against collections.abc.Sequence:

from collections.abc import Sequence

isinstance(set(), Sequence)
# False
isinstance(list(), Sequence)
# True
isinstance(tuple(), Sequence)
# True

If one were to insist that ordered mappings should be included, i.e. that a dict (ordered as of Python 3.7), you could test against collections.abc.Reversible:

isinstance(set(), Reversible)
# False
isinstance(list(), Reversible)
# True
isinstance(tuple(), Reversible)
# True
isinstance(dict(), Reversible)
# True
user2390182
  • 72,016
  • 6
  • 67
  • 89
  • Says `False` for `dict()`. Even in Python 3.9. – Kelly Bundy Dec 13 '20 at 23:54
  • Yes, and that's surprising how? A `dict` **is** a mapping. – user2390182 Dec 14 '20 at 05:40
  • It isn't. That's rather the point. If I'd call anything here "surprising", then that this was accepted even though it doesn't work for one of the main data types. – Kelly Bundy Dec 14 '20 at 05:43
  • I still don't get it. A `dict` (just like a set) is clearly not a sequence, so it works just fine. It is **not** *non-mapping*, it is **not** *ordered*, and its `__getitem__` method does **not** *provide indexed acces*, but keyed access. So it fails to have any of three properties of a sequence that the answer mentions. – user2390182 Dec 14 '20 at 06:04
  • `dict`s **are** ordered. Have been since Python 3.7, which came out almost 2.5 years ago already. They're also **collections**, and that's what the question is about (it says so three times). Ordered collections. Dicts are. This answer's method doesn't determine that. – Kelly Bundy Dec 14 '20 at 14:18
  • What do you mean with "implentational coincidents" and "inherent properties"? Dict's orderedness is guaranteed by the language spec! To me, the question looks like just examples, not like that's all the collection types they're interested in. Otherwise they could've just checked whether they have a list or tuple (or whether they *don't* have a set) and wouldn't have had to ask. No, I don't know a better answer, I'd like to see one if there is a better way, and I worry this answer existing and being accepted makes it look like "case closed" and might deter better ones. – Kelly Bundy Dec 14 '20 at 16:12
  • There you go ;-) `Reversible` is probably the best you get. No guarantees for custom types though. – user2390182 Dec 14 '20 at 16:26
  • Hmm, ok, that at least gets all those standard types right (and `str`, `collections.deque` and `range`, too). Although in 3.7 it reports `False` for `dict`, as that was ordered but not yet reversible. But in general I agree that ordered collections likely are reversible and non-ordered ones very likely aren't. (Was kinda disappointed to find out now that `itertools.count()` isn't regarded as a `Collection`.) – Kelly Bundy Dec 14 '20 at 16:48
  • Lazy iterators such as `count` are conceptually quite different from collections. After all, in order to *collect* all (not considering `count`'s infinity) the items, you'd have to exhaust it, and still be left with some other object to do the collecting. The laziness and infinity would also make it really hard to define a reverse, even though you could argue that it is ordered. – user2390182 Dec 14 '20 at 17:02
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/225946/discussion-between-schwobaseggl-and-kelly-bundy). – user2390182 Dec 14 '20 at 17:05