1

I have a simple issue. I want to shorten the expression of the kronecker product

a=np.matrix('1 0; 0 1')
b=np.matrix('1 0; 0 1')
C=np.kron(a,b)

to something like this

C=a.k(b)

I have been flogging google for a while, but I do not quite find the solution to this. I understand that there are workarounds which work perfectly fine, but I would like to understand how to add a function to a numpy object like this. Or any object. I want to learn, not do.

Any ideas? Thanks in advance!

Leviathan
  • 181
  • 6
  • 1
    Although you mention that you don't want to create a new functionality, wouldn't it be the most straightforward to create a new class that inherits all the functionality from matrix? – lcdumort Nov 22 '21 at 22:24
  • I agree. Creating a class that inherits from matrix and has this extra method sounds a lot less brittle than monkeypatching a method onto an existing class. – CrazyChucky Nov 22 '21 at 22:39
  • 1
    How about `k = np.kron` then you can just call `k(a, b)`? – John Zwinck Nov 22 '21 at 22:43
  • Hello guys. I realize that I can just create a new class, or a short cut, but I want to do this for understanding's sake. Can I not extend the numpy matrix by this function within this code and only for the lifespan of this code? I do not understand how I *would* do this, and it bothers me. – Leviathan Nov 23 '21 at 11:11

2 Answers2

1

If you don't want to subclass the Matrix, you can monkeypatch your method at runtime. That means that you just create the function you want to add to the matrix class and than assign it to the attribute name of the class you want the method name to be, in this instance k. This works, because in Python, functions are first class objects, meaning that you can assign them to a variable (or class attribute), which is equivalent to defining the function in the actual class.

def kron(self, other):
    return np.kron(self, other)
    
np.matrix.k = kron

After that, you can call:

>>> a.k(b)
matrix([[1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 1, 0],
        [0, 0, 0, 1]])

You can read more about monkeypatching here: What is monkey patching?

sunnytown
  • 1,844
  • 1
  • 6
  • 13
  • It's the same as you are doing below. – sunnytown Dec 02 '21 at 10:20
  • But it does not rely on the "setattr()" function that I had to put in. It looks like a nicer solution, even if it does the same. I did not know what "setattr()" does. Your post makes it obvious. – Leviathan Dec 02 '21 at 10:23
  • `setattr` is setting the attribute. It does exactly what my solution does with the `=` symbol. Infact, the `np.matrix.k = kron` invokes `setattr(np.matrix, 'k', kron)` under the hood. You can read it as: "Set the function kron as an attribute of np.matrix and name it k." – sunnytown Dec 02 '21 at 10:32
  • Hi there again. I encountered a problem, which I have put below, in my previous answer, because I cannot format in the comment. – Leviathan Dec 02 '21 at 11:18
0

I found the answer

a=np.matrix('1 0; 0 1')
b=np.matrix('1 0; 0 1')

def k(self, b): # Have to add self since this will become a method
    return np.kron(self,b)
setattr(np.matrix, 'k', k)

print(a.k(b))

Gives me the correct result.

Link that helped me with this: https://mgarod.medium.com/dynamically-add-a-method-to-a-class-in-python-c49204b85bd6

S.B
  • 13,077
  • 10
  • 22
  • 49
Leviathan
  • 181
  • 6