Different behavior of arithmetics on dtype float 'object' and 'float'

前端 未结 3 1150
一个人的身影
一个人的身影 2020-12-21 11:55

Hi guys im just a rookie in python (even in programming) so my question might sound very basic but i have a hard time to understand this.

Why is the selective behavi

相关标签:
3条回答
  • 2020-12-21 12:30

    @Warren points out that square 'delegates' to multiply. I verified this by making an object array that includes a list:

    In [524]: arr = np.array([np.arange(3), 3, [3,4]])
    In [525]: np.square(arr)
    TypeError: can't multiply sequence by non-int of type 'list'
    

    square works on the rest of the array:

    In [526]: np.square(arr[:2])
    Out[526]: array([array([0, 1, 4]), 9], dtype=object)
    

    sqrt doesn't work on any of these:

    In [527]: np.sqrt(arr)
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-527-b58949107b3d> in <module>()
    ----> 1 np.sqrt(arr)
    
    AttributeError: 'numpy.ndarray' object has no attribute 'sqrt'
    

    I can make sqrt work with a custom class:

    class Foo(float):
        def sqrt(self):
            return self**0.5
    
    In [539]: arr = np.array([Foo(3), Foo(2)], object)
    In [540]: np.square(arr)
    Out[540]: array([9.0, 4.0], dtype=object)
    In [541]: np.sqrt(arr)
    Out[541]: array([1.7320508075688772, 1.4142135623730951], dtype=object)
    
    0 讨论(0)
  • 2020-12-21 12:30

    Not sure if this is the reason but my guess is:

    What if your objects were instances of your own homemade class? Numpy cannot do anything else but hope that you have defined a sqrt method in your class and let it do the work. So I assume that's what it does here, but in your case your objects are floats, and although np.sqrt(some_random_float) makes sense, some_random_float.sqrt() doesn't because the AttributeError: 'float' object has no attribute 'sqrt'.

    Typically numpy is designed and optimized for numerical computations, while using it with generic dtype=object can be sometime convenient, you shouldn't assume everything will always run seamlessly in this case...

    0 讨论(0)
  • 2020-12-21 12:49

    In Python, everything is an object.

    Operators are implemented on objects either as special methods (as seen from the __ prefix in the method name, such as a + b is syntactic sugar for a.__add__(b) or they are aliases for builtin functions that take the objects as arguments (such as a ** b is syntatic sugar for pow(a, b). And often, the functions themselves are aliases back to special methods on the objects (like iter(a) just returns a.__iter__()).

    Numpy adds further syntactic sugar, where it implements functions that behave based on the type of numpy object. As stated above, a numpy array with dtype of object pushes the implementation of the operator back down to the object type of the element in the array (so basically, np.square(a) is semantically similar to array = map(lambda x: x*x, array) which is really evaluated as array = map(lambda x: x.__mult__(x), array).

    Note that sqrt does not exist as a builtin function (it is either imported from the math module in the standard library or np's implementation or by using **0.5 (which is really pow(x, 0.5)), and therefore a normal float object will not have a method that implements it.

    0 讨论(0)
提交回复
热议问题