Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NEP: Proposal for __duckarray__ protocol (#14170)
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
Showing
1 changed file
with
106 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |