Skip to content

Commit

Permalink
NEP: Proposal for __duckarray__ protocol (#14170)
Browse files Browse the repository at this point in the history
This NEP proposes the introduction of the __duckarray__ protocol, as described in high-level by NEP-22 and further discussed in #13831 .

We have another idea by @shoyer on how to handle duck array typing through __array_function__, as mentioned in #13831 (comment):

we could consider adding a like argument to duckarray. That would require changing the protocol from the simplified proposal above -- maybe to use array_function instead of a dedicated protocol like duckarray? I haven't really thought this through.
The idea above seems viable, and perhaps more complete as well. That said, I want to either extend this NEP to cover that, or maybe write a separate NEP so we can discuss and judge which one is a better solution. In the meantime, let's start discussing the text here.
  • Loading branch information
pentschev authored and seberg committed Aug 5, 2019
1 parent 57feadb commit 044f513
Showing 1 changed file with 106 additions and 0 deletions.
106 changes: 106 additions & 0 deletions doc/neps/nep-0030-duck-array-protocol.rst
@@ -0,0 +1,106 @@
======================================================
NEP 30 — Duck Typing for NumPy Arrays - Implementation
======================================================

:Author: Peter Andreas Entschev <pentschev@nvidia.com>
:Author: Stephan Hoyer <shoyer@google.com>
:Status: Draft
:Type: Standards Track
:Created: 2019-07-31
:Updated: 2019-07-31
:Resolution:

Abstract
--------

We propose the ``__duckarray__`` protocol, following the high-level overview
described in NEP 22, allowing downstream libraries to return arrays of their
defined types, in contrast to ``np.asarray``, that coerces those ``array_like``
to NumPy arrays.

Detailed description
--------------------

NumPy's API, including array definitions, is implemented and mimicked in
countless other projects. By definition, many of those arrays are fairly
similar in how they operate to the NumPy standard. The introduction of
``__array_function__`` allowed dispathing of functions implemented by several
of these projects directly via NumPy's API. This introduces a new requirement,
returning the NumPy-like array itself, rather than forcing a coercion into a
pure NumPy array.

For the purpose above, NEP 22 introduced the concept of duck typing to NumPy
arrays. The suggested solution described in the NEP allows libraries to avoid
coercion of a NumPy-like array to a pure NumPy array where necessary, while
still allowing that NumPy-like array libraries that do not wish to implement
the protocol to coerce arrays to a pure Numpy array via ``np.asarray``.

Implementation
--------------

The implementation idea is fairly straightforward, requiring a new function
``duckarray`` to be introduced in NumPy, and a new method ``__duckarray__`` in
NumPy-like array classes. The new ``__duckarray__`` method shall return the
downstream array-like object itself, such as the ``self`` object, while the
``__array__`` method returns ``TypeError``.

The new NumPy ``duckarray`` function can be implemented as follows:

.. code:: python
def duckarray(array_like):
if hasattr(array_like, '__duckarray__'):
return array_like.__duckarray__()
return np.asarray(array_like)
Example for a project implementing NumPy-like arrays
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Now consider a library that implements a NumPy-compatible array class called
``NumPyLikeArray``, this class shall implement the methods described above, and
a complete implementation would look like the following:

.. code:: python
class NumPyLikeArray:
def __duckarray__(self):
return self
def __array__(self):
return TypeError
The implementation above exemplifies the simplest case, but the overall idea
is that libraries will implement a ``__duckarray__`` method that returns the
original object, and ``__array__`` solely for the purpose of raising a
``TypeError``, thus preventing unintentional NumPy-coercion. In case of existing
libraries that don't already implement ``__array__`` but would like to use duck
array typing, it is advised that they they introduce both ``__array__`` and
``__duckarray__`` methods.

Backward compatibility
----------------------

This proposal does not raise any backward compatibility issues within NumPy,
given that it only introduces a new function. However, downstream libraries
that opt to introduce the ``__duckarray__`` protocol may choose to remove the
ability of coercing arrays back to a NumPy array via ``np.array`` or
``np.asarray`` functions, preventing unintended effects of coercion of such
arrays back to a pure NumPy array (as some libraries already do, such as CuPy
and Sparse), but still leaving libraries not implementing the protocol with the
choice of utilizing ``np.duckarray`` to promote ``array_like`` objects to pure
NumPy arrays.

Previous proposals and discussion
---------------------------------

The duck typing protocol proposed here was described in a high level in
`NEP 22 <https://numpy.org/neps/nep-0022-ndarray-duck-typing-overview.html>`_.

Additionally, longer discussions about the protocol and related proposals
took place in
`numpy/numpy #13831 <https://github.com/numpy/numpy/issues/13831>`_

Copyright
---------

This document has been placed in the public domain.

0 comments on commit 044f513

Please sign in to comment.