4

As mentioned here and here, this doesn't work anymore in numpy 1.7+ :

import numpy
A = numpy.array([1, 2, 3, 4], dtype=numpy.int16)
B = numpy.array([0.5, 2.1, 3, 4], dtype=numpy.float64)
A *= B

A workaround is to do:

def mult(a,b):
    numpy.multiply(a, b, out=a, casting="unsafe")

def add(a,b):
    numpy.add(a, b, out=a, casting="unsafe")

mult(A,B)

but that's way too long to write for each matrix operation!

How can override the numpy *= operator to do this by default?

Should I subclass something?

Community
  • 1
  • 1
Basj
  • 41,386
  • 99
  • 383
  • 673
  • `A *= B` saves you only 3 characters over `mult(A,B)`. Can you articulate why you need to have the shortest method possible? – SethMMorton Jul 30 '16 at 18:55
  • @SethMMorton : *better explicit than implicit* : `*=` is standard among all major programming languages ; having to define a `mult` function is not natural – Basj Jul 30 '16 at 19:11
  • What do you want `A` to end up as here? – Eric Jul 30 '16 at 19:28
  • @Eric As `A` is an int array, and that we do inplace `*=`, I want `A` to stay an int at the end. – Basj Jul 30 '16 at 20:21

2 Answers2

6

You can use np.set_numeric_ops to override array arithmetic methods:

import numpy as np

def unsafe_multiply(a, b, out=None):
    return np.multiply(a, b, out=out, casting="unsafe")

np.set_numeric_ops(multiply=unsafe_multiply)

A = np.array([1, 2, 3, 4], dtype=np.int16)
B = np.array([0.5, 2.1, 3, 4], dtype=np.float64)
A *= B

print(repr(A))
# array([ 0,  4,  9, 16], dtype=int16)
ali_m
  • 71,714
  • 23
  • 223
  • 298
1

You can create a general function and pass the intended attribute to it:

def calX(a,b, attr):
    try:
        return getattr(numpy, attr)(a, b, out=a, casting="unsafe")
    except AttributeError:
        raise Exception("Please enter a valid attribute")

Demo:

>>> import numpy
>>> A = numpy.array([1, 2, 3, 4], dtype=numpy.int16)
>>> B = numpy.array([0.5, 2.1, 3, 4], dtype=numpy.float64)
>>> calX(A, B, 'multiply')
array([ 0,  4,  9, 16], dtype=int16)
>>> calX(A, B, 'subtract')
array([ 0,  1,  6, 12], dtype=int16)

Note that if you want to override the result you can just assign the function's return to the first matrix.

A = calX(A, B, 'multiply')
Mazdak
  • 105,000
  • 18
  • 159
  • 188
  • Nice but this is not shorter than `mult(A,B)` with `def mult(a,b): numpy.multiply(a, b, out=a, casting="unsafe")`... What I want is override `A*=B` – Basj Jul 30 '16 at 12:37
  • @Basj This is a general way, which makes you don't define a function for all operations. Also you don't need to override anything. – Mazdak Jul 30 '16 at 12:40
  • @Basj If you consist to use in-place operators you better to create a custom matrix object and define it's operators manually which still you'd need to do this for all the operators. – Mazdak Jul 30 '16 at 12:41