How can we define the __mult__ method to return a Complex object?

Click For Summary
SUMMARY

The discussion focuses on implementing a Python class named Vector that represents a mathematical vector, including methods for initialization, movement, and addition. The __init__ method initializes the vector with coordinates and calculates its Euclidean norm. Participants also explore subclassing to create a Point class and a Complex class, which inherits from Point and implements complex number multiplication through the __mul__ method. The conversation emphasizes using lists or tuples for coordinates and the importance of method inheritance in Python.

PREREQUISITES
  • Understanding of Python classes and object-oriented programming
  • Familiarity with mathematical concepts such as vectors and complex numbers
  • Knowledge of Python's built-in functions and libraries, particularly math.sqrt
  • Basic understanding of subclassing in Python
NEXT STEPS
  • Implement the __mul__ method in the Complex class for complex number multiplication
  • Research how to effectively use inheritance in Python classes
  • Explore the use of numpy for vector operations to enhance performance
  • Learn about operator overloading in Python to customize behavior for mathematical operations
USEFUL FOR

Python developers, mathematicians, and anyone interested in implementing mathematical concepts through programming, particularly in the context of object-oriented design.

mathmari
Gold Member
MHB
Messages
4,984
Reaction score
7
Hey! 😊

Construct a class named Vector that expresses the meaning of the vector of numbers. The initialization function, __init__ will take as a argument a tuple corresponding to the vector. This tuple will be stored in the variable named coord. Also, __init__ will calculate the Euclidean measure of the vector and store it in the variable norm2. How do we write the tuple as an argument of the function?

Do we write just :
Code:
class Vector : 
    
    def __init__(self, coord): 
         pass

? Or do we have to the elements there and insert these into the tuple?

:unsure:
 
Technology news on Phys.org
Hi mathmari,

Ok so a tuple is an object type that is stored in round parentheses.

Here's an example of how this would work as a list. Can you make it a tuple?

Code:
class Vector :
    
    def __init__(self, coord):
         self.coord = coordvec = Vector([1,2,3])

print(type(vec.coord))
 
Here's my solution to this:
Code:
from math import sqrt

class Vector:
    def __init__(self, coord):
        self.coord = coord
        self.norm2 = sqrt(sum(x**2 for x in self.coord))

vec = Vector((1, 2, 3))
print(vec.norm2)
 
I wish you a Happy New Year! 🎉

Jameson said:
Here's my solution to this:
Code:
from math import sqrt

class Vector:
    def __init__(self, coord):
        self.coord = coord
        self.norm2 = sqrt(sum(x**2 for x in self.coord))

vec = Vector((1, 2, 3))
print(vec.norm2)

I got it!Next I want to write the method move (self, i, x). This method moves the vector by x in the direction of the i-th coordinate. That is, it simply adds the number x to the i-position of the coordinates and updates this variable with the new value. The variables should be updated at norm2. The method does not returns anything, just shifts the vector.

For that I wrote the following :

Code:
def move(self, i, x) :
        if (i < 0 or i > self.dim) :
            print("Error")
        else :
            self.coord[i] += x
            self.norm2 = sqrt(sum(x**2 for x in self.coord))

I defined as self.dim the dimension of the given vector inside the __init__
I get an error at "self.coord += x". Is that wrong to give the new value to the i-th coordinate of the vector?
Also when it is said to update the norm2, is it meant to write that again inside the method or is something else meant?

:unsure:After that I want to write the method __add __ (self, other). This (magic) method is called when the object is involved in algebraic addition expressions. When the variable other is a number then it is added in the vector coordinates and returns a new object of the Vector class. When the variable other is the object of the Vector class, then it is added by point of two vectors and the new vector is returned.

Example :
v = Vector((5,6,7))
w = Vector((1,2,3))
v+w = (6, 8, 10)
v+3 = (5, 6, 7)

For that I wrote :

Code:
    def __add__(self, other):
        if isinstance(other, Vector):
            return Vector(self.coord + other.coord)
        else :
            return Vector(x + other for x in self.coord)

But that doesn't work. How can we write then to add each component of the first vector with the corresponding component of the second vector?:unsure:
 
Last edited by a moderator:
Let's make one change from using tuples to using numpy arrays. Tuples are immutable, meaning cannot be changed, whereas numpy arrays are mutable.

Code:
from math import sqrt
import numpy as npclass Vector:
    def __init__(self, coord):
        self.coord = np.asarray(coord)
        self.norm2 = sqrt(sum(x**2 for x in self.coord))

vec = Vector([1, 2, 3])

print(vec.norm2)

Now try your move code...
 
Jameson said:
Let's make one change from using tuples to using numpy arrays. Tuples are immutable, meaning cannot be changed, whereas numpy arrays are mutable.

Code:
from math import sqrt
import numpy as npclass Vector:
    def __init__(self, coord):
        self.coord = np.asarray(coord)
        self.norm2 = sqrt(sum(x**2 for x in self.coord))

vec = Vector([1, 2, 3])

print(vec.norm2)

Now try your move code...

Ahh ok! :geek: Since we haven't seen the numpy library yet, do we maybe do the changes of the tuples using lists? I mean to turn the tuple into a list then make the desired changes and then turn the result again into a tuple.

:unsure:
 
Actually a list works the same way it seems. I removed the above numpy reference and this seems to work.

Code:
class Vector:
    def __init__(self, coord):
        self.coord = coord
        self.norm2 = sqrt(sum(x**2 for x in self.coord))
    
    def move(self, i, x):
        if (i < 0):
            print("Error")
        else :
            self.coord[i] += x
            self.norm2 = sqrt(sum(x**2 for x in self.coord))vec = Vector([1, 2, 3])

print(vec.norm2)
vec.move(1, 1)
print(vec.coord)
 
mathmari said:
After that I want to write the method __add __ (self, other). This (magic) method is called when the object is involved in algebraic addition expressions. When the variable other is a number then it is added in the vector coordinates and returns a new object of the Vector class. When the variable other is the object of the Vector class, then it is added by point of two vectors and the new vector is returned.

Example :
v = Vector((5,6,7))
w = Vector((1,2,3))
v+w = (6, 8, 10)
v+3 = (5, 6, 7)

For that I wrote :

Code:
    def __add__(self, other):
        if isinstance(other, Vector):
            return Vector(self.coord + other.coord)
        else :
            return Vector(x + other for x in self.coord)

But that doesn't work. How can we write then to add each component of the first vector with the corresponding component of the second vector?:unsure:

Ok for this part I would try something like this as a hint, if we are using lists to input.

Code:
    def __add__(self, other):
        if len(self.coord) != len(other.coord):
            print("Error")
        else:
            new_coord = []
            for i in range(len(self.coord)):

Loop over each Vector's coordinates and add them to the new list, then make that list part of a new Vector.
 
Last edited:
I see! Now my code works properly! :geek: Now I want to construct a Point class that expresses the meaning of the point in the plane ($\mathbb{R}^2$). We can define it as a subclass of Vector. Point should additionally include the following methods:
- get_angle(self)
- get_polar(self)

So do we just call a Vector instance (x,y) for Point ? Or how do we define that? :unsure:
 
  • #10
You make subclasses in Python like this...
Code:
class Point(Vector):
    def __init__(self, coord):

You still need to initialize all the proper inputs, but if you write a subclass like this then Point should have a move() method based on inheriting from Vector.
 
  • #11
Jameson said:
You make subclasses in Python like this...
Code:
class Point(Vector):
    def __init__(self, coord):

You still need to initialize all the proper inputs, but if you write a subclass like this then Point should have a move() method based on inheriting from Vector.

Ah ok! So when we have saved both .py file in the same directory we can use also the functions that we defined at the class Vector for Point, right? :unsure:

So at this part of the exercise what do we have to define in __init__ ? Do we just write "pass" ? Or do we write "self.coord = coord" ? Or do we have the same __init__ as in the Vector class? And other than __init__ we just define the two methods "get_angle(self)" and "get_polar(self)", or not ? :unsure:
 
  • #12
The key word I saw that led me to use this idea was "subclass". One of the core functions of classes in Python is the ability to inherit from other classes into a subclass. Yes you will need to fill out the __init___ with all the key inputs, but it should auto carry over the methods that you wrote in Vector. So if you do this correctly, Point should have a move() method once you initialize it because it inherits that from Vector.

Try to finish the __init___ method and then test if you have a move method. There are multiple ways to do this but I don't want to make this too complicated. Then I would try to move on to writing get_angle() and get_polar(), yep.
 
  • #13
Jameson said:
The key word I saw that led me to use this idea was "subclass". One of the core functions of classes in Python is the ability to inherit from other classes into a subclass. Yes you will need to fill out the __init___ with all the key inputs, but it should auto carry over the methods that you wrote in Vector. So if you do this correctly, Point should have a move() method once you initialize it because it inherits that from Vector.

Try to finish the __init___ method and then test if you have a move method. There are multiple ways to do this but I don't want to make this too complicated. Then I would try to move on to writing get_angle() and get_polar(), yep.
I wrote that and it works! :giggle:
The angle is calculated as arctan(y/x), right? :unsure:

After that I want to do the following :

Construct a class Complex that expresses the meaning of the point in the complex plane (C). You can define this class as a subclass of Point. The Complex should implement the multiplication (__mul__) as the multiplication of complex numbers. Implement methods to get the real (self.re) and the imaginary (self.im) part of the number.

I have some questions about that.. For the multiplication do we return a tuple in the form [real part, imaginary part] ? I mean $[ac-bd, ad+bc]$ ? Or what should the __mul__ return? :unsure:

To give the real and the imaginary part do we not just give the first and the second coordinate? Or what should we do here exactly? :unsure:
 
  • #14
I'm not really sure why we want to make Complex a subclass of Point, but it seems for both they want to assume that the input space is $\mathbb{R}^2$. I would add a condition in the __init__ method to check for this perhaps, just to be safe.

After that yep you can made the __mult__ method and define it like you suggested. it should return a Complex object. When we add two Complex objects we return a new Complex object, and similarly so if we multiply them.
 

Similar threads

  • · Replies 9 ·
Replies
9
Views
1K
  • · Replies 23 ·
Replies
23
Views
2K
  • · Replies 43 ·
2
Replies
43
Views
4K
  • · Replies 4 ·
Replies
4
Views
2K
Replies
5
Views
15K
  • · Replies 15 ·
Replies
15
Views
5K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 3 ·
Replies
3
Views
1K
  • · Replies 3 ·
Replies
3
Views
1K
  • · Replies 3 ·
Replies
3
Views
1K