Improve and accept PEP 424 (__length_hint__).
This commit is contained in:
parent
9962846ad1
commit
03909e4c50
64
pep-0424.txt
64
pep-0424.txt
|
@ -3,7 +3,7 @@ Title: A method for exposing a length hint
|
|||
Version: $Revision$
|
||||
Last-Modified: $Date
|
||||
Author: Alex Gaynor <alex.gaynor@gmail.com>
|
||||
Status: Draft
|
||||
Status: Accepted
|
||||
Type: Standards Track
|
||||
Content-Type: text/x-rst
|
||||
Created: 14-July-2012
|
||||
|
@ -13,18 +13,19 @@ Post-History: http://mail.python.org/pipermail/python-dev/2012-July/120920.html
|
|||
Abstract
|
||||
========
|
||||
|
||||
CPython currently defines an ``__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 estimated returned by
|
||||
``__length_hint__``. Types can then define ``__length_hint__`` which are not
|
||||
sized, and thus should not define ``__len__``, but can estimate or compute a
|
||||
size (such as many iterators).
|
||||
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).
|
||||
|
||||
Proposal
|
||||
========
|
||||
Specification
|
||||
=============
|
||||
|
||||
This PEP proposes formally documenting ``__length_hint__`` for other
|
||||
interpreter and non-standard library Python to implement.
|
||||
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
|
||||
|
@ -32,21 +33,23 @@ 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 is added, having the
|
||||
follow semantics (which define how ``__length_hint__`` should be used::
|
||||
In addition, a new function ``operator.length_hint`` hint is added,
|
||||
with the follow semantics (which define how ``__length_hint__`` should
|
||||
be used)::
|
||||
|
||||
def length_hint(obj, default):
|
||||
"""
|
||||
Return an estimate of the number of items in obj. This is
|
||||
useful for presizing containers when building from an iterable.
|
||||
def length_hint(obj, default=0):
|
||||
"""Return an estimate of the number of items in obj.
|
||||
|
||||
If the object supports len(), the result will be exact. Otherwise, it
|
||||
may over or underestimate by an arbitrary amount. The result will be an
|
||||
integer >= 0.
|
||||
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:
|
||||
if <obj has a __len__ method>:
|
||||
return len(obj)
|
||||
except TypeError:
|
||||
else:
|
||||
try:
|
||||
get_hint = obj.__length_hint__
|
||||
except AttributeError:
|
||||
|
@ -55,13 +58,18 @@ follow semantics (which define how ``__length_hint__`` should be used::
|
|||
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 (%r) must be >= 0" % hint)
|
||||
return hint
|
||||
raise TypeError("Length hint must be an integer, not %r" %
|
||||
type(hint))
|
||||
return max(hint, 0)
|
||||
|
||||
Callers are required to provide a default value, because there is no sane
|
||||
return value for objects which do not provide a length or length hint.
|
||||
Note: there is no good way to spell "obj has a __len__ method" in pure
|
||||
Python. In CPython, this comes down to checking for a ``sq_length``
|
||||
slot. Other implementations presumably have their own way of
|
||||
checking. Calling ``len(obj)`` and catching TypeError is not quite
|
||||
correct (as it would assume no __len__ method exists when in fact one
|
||||
exists but calling it raises TypeError); checking ``hasattr(obj,
|
||||
'__len__')`` likewise is incorrect if obj is a class defining a
|
||||
``__len__`` method for its instances.
|
||||
|
||||
|
||||
Rationale
|
||||
|
|
Loading…
Reference in New Issue