16

I'm reading through the Numpy docs, and it appears that the functions np.prod(...), np.product(...) and the ndarray method a.prod(...) are all equivalent.

Is there a preferred version to use, both in terms of style/readability and performance? Are there different situations where different versions are preferable? If not, why are there three separate but very similar ways to perform the same operation?

miradulo
  • 28,857
  • 6
  • 80
  • 93
dkv
  • 6,602
  • 10
  • 34
  • 54
  • 11
    That's Zen of NumPy. "There should be three-- and preferably more than three -- non-obvious ways to do it." – wim Apr 16 '18 at 18:08
  • 2
    Except, if it's an alias, they do more than just rename the function. `prod` returns `return _methods._prod(a, axis=axis, dtype=dtype, out=out, **kwargs)` while `product` returns `return um.multiply.reduce(a, axis=axis, dtype=dtype, out=out, **kwargs)` but they're both in the `fromnumeric` module. It's not so simple to see how it's equivalent... – roganjosh Apr 16 '18 at 18:13
  • 3
    @roganjosh I don't follow... in every case, it looks to me like `umath.multiply.reduce` ends up being called. – miradulo Apr 16 '18 at 18:25
  • @miradulo yeah, I followed it back and you're correct – roganjosh Apr 16 '18 at 18:26
  • @miradulo actually, this seems to have changed quite a bit between my numpy version (1.13.1) and master. It's clearer now in the source that they are the same thing, I was comparing apples and oranges in some senses by looking at the source in my editor and online – roganjosh Apr 16 '18 at 18:31
  • 1
    Be careful if performance is really relevant. Depending on your usecase there may be better (and also easy to use) methods: https://stackoverflow.com/a/49321971/4045774 – max9111 Apr 16 '18 at 20:13

2 Answers2

13

As of the master branch today (1.15.0), np.product just uses np.prod, and may be deprecated eventually. See MAINT: Remove duplicate implementation for aliased functions. #10653.

And np.prod and ndarray.prod both end up calling umath.multiply.reduce, so there is really no difference between them, besides the fact that the free functions can accept array-like types (like Python lists) in addition to NumPy arrays.

Prior to this, like in NumPy 1.14.2, the documentation claimed np.product and np.prod were the same, but there were bugs because of the duplicated implementation that Parag mentions. i.e. Eric Weiser's example from #10651:

>>> class CanProd(object):
        def prod(self, axis, dtype, out): return "prod"  
>>> np.product(CanProd())
<__main__.CanProd object at 0x0000023BAF7B29E8>
>>> np.prod(CanProd())
'prod'

So in short, now they're the same, and favor np.prod over np.product since the latter is an alias that may be deprecated.

miradulo
  • 28,857
  • 6
  • 80
  • 93
  • 2
    Something to add; regardless of the alias, it's usually slightly faster to call the method on the array object. `arr = np.random.randint(1, 100, size=10000)` --> `timeit np.prod(arr)` of `10.3 µs ± 27.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)`. `%timeit arr.prod()` of `9.58 µs ± 18.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)` – roganjosh Apr 16 '18 at 18:52
5

This is what I could gather from the source codes of NumPy 1.14.0. For the answer relevant to the current Master branch (NumPy 1.15.0), see the answer of miradulo.

  • For an ndarray, prod() and product() are equivalent.

  • For an ndarray, prod() and product() will both call um.multiply.reduce().

  • If the object type is not ndarray but it still has a prod method, then prod() will return prod(axis=axis, dtype=dtype, out=out, **kwargs) whereas product will try to use um.multiply.reduce.

  • If the object is not an ndarray and it does not have a prod method, then it will behave as product().

  • The ndarray.prod() is equivalent to prod().

I am not sure about the latter part of your question regarding preference and readability.

Autonomous
  • 8,935
  • 1
  • 38
  • 77