Python Enhancement Proposals

PEP 424 – A method for exposing a length hint

PEP
424
Title
A method for exposing a length hint
Author
Alex Gaynor <alex.gaynor at gmail.com>
Status
Final
Type
Standards Track
Created
14-Jul-2012
Python-Version
3.4
Post-History
https://mail.python.org/pipermail/python-dev/2012-July/120920.html

Contents

Abstract

CPython currently defines a __length_hint__ method on several types, such as various iterators. This method is then used by various other functions (such as list) to presize lists based on the estimate returned by __length_hint__. Types which are not sized, and thus should not define __len__, can then define __length_hint__, to allow estimating or computing a size (such as many iterators).

Specification

This PEP formally documents __length_hint__ for other interpreters and non-standard-library Python modules to implement.

__length_hint__ must return an integer (else a TypeError is raised) or NotImplemented, and is not required to be accurate. It may return a value that is either larger or smaller than the actual size of the container. A return value of NotImplemented indicates that there is no finite length estimate. It may not return a negative value (else a ValueError is raised).

In addition, a new function operator.length_hint hint is added, with the following semantics (which define how __length_hint__ should be used):

def length_hint(obj, default=0):
    """Return an estimate of the number of items in obj.

    This is useful for presizing containers when building from an
    iterable.

    If the object supports len(), the result will be
    exact. Otherwise, it may over- or under-estimate by an
    arbitrary amount. The result will be an integer >= 0.
    """
    try:
        return len(obj)
    except TypeError:
        try:
            get_hint = type(obj).__length_hint__
        except AttributeError:
            return default
        try:
            hint = get_hint(obj)
        except TypeError:
            return default
        if hint is NotImplemented:
            return default
        if not isinstance(hint, int):
            raise TypeError("Length hint must be an integer, not %r" %
                            type(hint))
        if hint < 0:
            raise ValueError("__length_hint__() should return >= 0")
        return hint

Rationale

Being able to pre-allocate lists based on the expected size, as estimated by __length_hint__, can be a significant optimization. CPython has been observed to run some code faster than PyPy, purely because of this optimization being present.

Source: https://github.com/python/peps/blob/master/pep-0424.txt

Last modified: 2021-02-09 16:54:26 GMT