What exactly are "containers" in python? (And what are all the python container types?)

Bentley4 picture Bentley4 · Jul 20, 2012 · Viewed 50.2k times · Source

The python documentation frequently speaks of "containers". E.g. :

If check_circular is False (default: True), then the circular reference check for container types will be skipped and a circular reference will result in an OverflowError (or worse).

But I can't find any official definition of containers, neither a list of them.

Edit

For Python 2.7.3:

Checked builtin types which are containers:

(isinstance(object, collections.Container) returns True)

  1. Containers which have a __contains__ method defined:

    • All builtin sequence types: Lists, bytearrays, strings, unicode strings and tuples.
    • Dictionaries
    • All builtin set types: sets and frozensets
  2. Containers which do not have a __contains__ method defined:

    • xrange objects

Checked builtin types which are not containers:

(isinstance(object, collections.Container) returns False):

  • Int objects
  • Float objects
  • Long objects
  • Boolean objects
  • Module objects
  • File objects
  • Buffer objects
  • The None object

Tell me which other builtin types you have checked for isinstance(object, collections.Container) and I'll add them to the list.

Answer

ecatmur picture ecatmur · Jul 20, 2012

Containers are any object that holds an arbitrary number of other objects. Generally, containers provide a way to access the contained objects and to iterate over them.

Examples of containers include tuple, list, set, dict; these are the built-in containers. More container types are available in the collections module.

Strictly speaking, the collections.abc.Container abstract base class (collections.Container in Python2) holds for any type that supports the in operator via the __contains__ magic method; so if you can write x in y then y is usually a container, but not always: an important point of difference between containers and general iterables is that when iterated over, containers will return existing objects that they hold a reference to, while generators and e.g. file objects will create a new object each time. This has implications for garbage collection and deep object traversal (e.g. deepcopy and serialisation).

As an example, iter(lambda: random.choice(range(6)), 0) supports the in operator, but it is certainly not a container!

The intent of the Collections.abc.Container abstract base class in only considering the __contains__ magic method and not other ways of supporting the in operator is that a true container should be able to test for containment in a single operation and without observably changing internal state. Since Collections.abc.Container defines __contains__ as an abstract method, you are guaranteed that if isinstance(x, collections.abc.Container) then x supports the in operator.

In practice, then, all containers will have the __contains__ magic method. However, when testing whether an object is a container you should use isinstance(x, collections.abc.Container) for clarity and for forward compatibility should the Container subclass check ever be changed.