0

I came upon this post : Sympy to numpy causes the AttributeError: 'Symbol' object has no attribute 'cos', and would like to understand a bit more the origin of the exception.

To be more precise, Eric answered : "This type of error occurs when you call np.cos(a_symbol), which apparently translates under-the-hood in numpy to a_symbol.cos()." I would like to understand how/where this behaviour origins from : how does np.cos(x) can be translated under the hood into x.cos() ?

I tried to reproduce the raise of the exception, but couldn't trace it's origin:

import numpy as np
class toto:
    def __init__(self,x):
        self.x = x
foo = toto(4)

class tata:
    def __init__(self,x):
        self.x = x

    def cos(self):
        print(self.x)

bar = tata(5)

try:
    np.cos(foo)
except:
    np.cos(bar)

This prints 5.

Cheers

mocquin
  • 402
  • 3
  • 11
  • 1
    This occurs when a math function (at least `ufunc`) is applied to an object dtype array. `numpy` iterates through the object elements and tries to apply a similarly named method. I've answered a few similar attribute error questions. – hpaulj Feb 05 '19 at 17:07
  • This AttributeError also occurs when applied to a simple object (see my post that I edited) - there are no notion of array or iteration, am I right ? – mocquin Feb 05 '19 at 18:14
  • https://stackoverflow.com/questions/49662823/different-behavior-of-arithmetics-on-dtype-float-object-and-float is another exploration of this behavior. – hpaulj Feb 05 '19 at 18:15
  • `numpy` first makes an array from your object `np.cos( np.array(bar))`. – hpaulj Feb 05 '19 at 18:16
  • Another answer from @Eric, https://stackoverflow.com/questions/49971708/python-numpy-attributeerror-float-object-has-no-attribute-sin – hpaulj Feb 05 '19 at 18:49
  • @hpaulj so does every ufunc tries to "cast" input into array ? I realized that if the object has a \__array__() method that return an array-version of the object, the np.cos works just fine. Yet that doesn't explain how defining a cos() method makes it work as well... It seems that the array method take precedence over the cos method. – mocquin Feb 07 '19 at 16:22
  • `np.cos(x)` is handled in the same way as `np.cos([x,x,x])`. The key variable is what's the nature of `np.array(x)` or `np.array([x,x,x])`. Is the result a numeric dtype or object dtype? – hpaulj Feb 07 '19 at 18:12
  • Indeed : so basically, if my custom object has a \__array__ method, the result is sent to np.cos. If it has a numerical dtype, it all works fine, but if if has a "object" dtype, then we get the AttributeError for cos on the value that was cast into ndarray type (ex : np.cos(np.array(5, dtype=object)) raises an AttributeError 'int' object has no attribute 'cos'). BUT if my custom object has no \__array__ method, numpy tries to call the cos method of the custom object (ex : toto.cos()). – mocquin Feb 08 '19 at 12:31
  • But that doesn't explain why... ("source-code wise") – mocquin Feb 08 '19 at 13:16
  • I've never tried to locate the C code that handles object dtypes for `ufuncs`. – hpaulj Feb 08 '19 at 17:33

0 Answers0