Is there an official or common knowledge standard minimal interface for a "list-like" object?
Question:
I keep seeing functions and documentation like this and this (to name a few) which operate on or refer to list-like objects.
I’m quite aware of what exactly an actual list is (dir(list)
), and can deduce what (often varying) methods from a list are necessary in most references to a “list-like object”, however the number of times I see it referenced has left me with the following question:
Is there an official or common knowledge standard minimal interface for a “list-like” object? Is it as simple as actualizing__getitem__
, or is it agreed that additional things like __len__
and __setitem__
are required as well?
This may seem like semantics, but I can’t help but think that if there does not exist a standard minimal interface requirement, various ideas of “list-likeness” could cause some issues/improper handling. Perhaps this is just a slight downside to Python’s duck typing?
Answers:
The technical term for a “list-like object” is sequence. At the very least it supports ordering (i.e. two objects with the same elements but different order are not equal), indexing (foo[bar]
such that bar
is an integer less than the length of the sequence), and containment checking (in
), and has a given length. It should support iteration, but if not then Python will simulate it using indexing.
Pretty much any time you see “-like object” in Python documentation the author is being deliberately vague. The author has decided that enumerating all the required interfaces would be too much trouble, and is only saying that some of its interfaces are required. An object that implemented all the interfaces is guaranteed to work, but in most cases it will work with an object that implements much less.
With a “list-like object” probably the best you can do, short of inspecting the source code, is to infer whether it needs any of the mutable interfaces. If it only needs read-only access to the list, you can be pretty sure you don’t need to implement any of the mutable sequence operations.
If it says “list-like object or iterator” you can provide something that implements the much simpler iterator interface.
See the collections.abc
module. Of the abstract base classes listed there, list
in Python implements Iterable
, Container
, Sized
, Sequence
and MutableSequence
. Now, of these, Iterable
, Sequence
and MutableSequence
could be casually called list-like.
However, I would understand the term list-like to mean that it is a MutableSequence
– has at least the methods __getitem__
, __setitem__
, __delitem__
and __len__
, expecting also it to have the mixin methods mentioned in the documentation, such as append
.
If there is no need for __setitem__
and __delitem__
it should be called a sequence instead – the assumption is that if something accepts a sequence, it does not need to be mutable, thus str
, bytes
, tuple
etc also work there.
Your two links highlight the vagueness of the term:
The plotly API requires that the list-like
objects will be serialized to a JSON array by the internal PlotlyJSONEncoder
that delegates most of the encoding to the Python JSONEncoder
. However, the latter encodes only tuple
and list
(and subclasses) to a JSON array; thus the list-like here means a list
, a tuple
or subclasses thereof. A custom sequence object that is not a subclass of either will result in TypeError: [...] is not JSON serializable
.
The unzip recipe you linked to requires an object that behaves like a Sequence
, (mutability is not required), thus a tuple
or str
, or any custom object implementing Sequence
will do there.
TL;DR list-like is a vague term. It is preferable to use the terms iterable, sequence and mutable sequence instead, now that these are defined in collections.abc
.
I keep seeing functions and documentation like this and this (to name a few) which operate on or refer to list-like objects.
I’m quite aware of what exactly an actual list is (dir(list)
), and can deduce what (often varying) methods from a list are necessary in most references to a “list-like object”, however the number of times I see it referenced has left me with the following question:
Is there an official or common knowledge standard minimal interface for a “list-like” object? Is it as simple as actualizing__getitem__
, or is it agreed that additional things like __len__
and __setitem__
are required as well?
This may seem like semantics, but I can’t help but think that if there does not exist a standard minimal interface requirement, various ideas of “list-likeness” could cause some issues/improper handling. Perhaps this is just a slight downside to Python’s duck typing?
The technical term for a “list-like object” is sequence. At the very least it supports ordering (i.e. two objects with the same elements but different order are not equal), indexing (foo[bar]
such that bar
is an integer less than the length of the sequence), and containment checking (in
), and has a given length. It should support iteration, but if not then Python will simulate it using indexing.
Pretty much any time you see “-like object” in Python documentation the author is being deliberately vague. The author has decided that enumerating all the required interfaces would be too much trouble, and is only saying that some of its interfaces are required. An object that implemented all the interfaces is guaranteed to work, but in most cases it will work with an object that implements much less.
With a “list-like object” probably the best you can do, short of inspecting the source code, is to infer whether it needs any of the mutable interfaces. If it only needs read-only access to the list, you can be pretty sure you don’t need to implement any of the mutable sequence operations.
If it says “list-like object or iterator” you can provide something that implements the much simpler iterator interface.
See the collections.abc
module. Of the abstract base classes listed there, list
in Python implements Iterable
, Container
, Sized
, Sequence
and MutableSequence
. Now, of these, Iterable
, Sequence
and MutableSequence
could be casually called list-like.
However, I would understand the term list-like to mean that it is a MutableSequence
– has at least the methods __getitem__
, __setitem__
, __delitem__
and __len__
, expecting also it to have the mixin methods mentioned in the documentation, such as append
.
If there is no need for __setitem__
and __delitem__
it should be called a sequence instead – the assumption is that if something accepts a sequence, it does not need to be mutable, thus str
, bytes
, tuple
etc also work there.
Your two links highlight the vagueness of the term:
The plotly API requires that the list-like
objects will be serialized to a JSON array by the internal PlotlyJSONEncoder
that delegates most of the encoding to the Python JSONEncoder
. However, the latter encodes only tuple
and list
(and subclasses) to a JSON array; thus the list-like here means a list
, a tuple
or subclasses thereof. A custom sequence object that is not a subclass of either will result in TypeError: [...] is not JSON serializable
.
The unzip recipe you linked to requires an object that behaves like a Sequence
, (mutability is not required), thus a tuple
or str
, or any custom object implementing Sequence
will do there.
TL;DR list-like is a vague term. It is preferable to use the terms iterable, sequence and mutable sequence instead, now that these are defined in collections.abc
.