Home > Software design >  How to make a class return a value?
How to make a class return a value?

Time:01-01

Consider the following example:

import numpy as np

class Vector:
    def __init__(self, x, y, z):
        self._vector = np.array([x, y, z])
        self._magnitude = np.linalg.norm(self._vector)
        self._direction = self._vector/self._magnitude

    @property
    def magnitude(self) -> float:
        return self._magnitude

    @property
    def direction(self) -> np.ndarray:
        return self._direction


vec = Vector(10, 4, 2)
print(vec) # <__main__.Vector object at 0x0000027BECAAFEE0>
print(vec.magnitude) # 10.954451150103322
print(vec.direction) # [0.91287093 0.36514837 0.18257419]

When I try to print(vec) it returns the allocated memory address and not the value of the array, which should be [10, 4, 2].

NOTE: I don't want to use __repr__ because in that way I would get a string and I need the actual type to be returned. The one above is just a small example.

CodePudding user response:

If you want a specific thing to be printed when you send your class to the print function, you need to overload the __str__ or __repr__ functions:

def __str__(self):
    return str(self._vector)

def __repr__(self):
    return str(self._vector)

You need to use one of these because print simply takes the string representation of whatever is sent to it and prints it to the screen. If you're looking for a function that returns self._vector as an object that you can then print, then you should write a function to do that:

@property
def value(self):
    return tuple(self._vector)

After reading the comments, it seems that what you actually want is the ability to modify self._vector arithmetically. You can do this by overloading, __add__, __sub__, __mul__, __div__:

def __add__(self, other):
    result = self._vector   other._vector
    return Vector(result[0], result[1], result[2])

def __sub__(self, other):
    result = self._vector - other._vector
    return Vector(result[0], result[1], result[2])

def __mul__(self, other):
    result = self._vector * other
    return Vector(result[0], result[1], result[2])

def __div__(self, other):
    result = self._vector / other
    return Vector(result[0], result[1], result[2])

Implementing these will allow you to do the following:

a = Vector(1, 2, 3)
b = Vector(4, 5, 6)
a   b   # [5, 7, 9]
b - a   # [3, 3, 3]
2 * a   # [2, 4, 6]
a / 2   # [0.5, 1, 1.5]

CodePudding user response:

You can use a getter property to return the value since you don't want to use __repr__. The same way you used property to return magnitude and direction.

Your code should look like this

import numpy as np

class Vector:
    def __init__(self, x, y, z):
        self._vector = np.array([x, y, z])
        self._magnitude = np.linalg.norm(self._vector)
        self._direction = self._vector/self._magnitude

    @property
    def vector(self) -> np.ndarray:
        return self._vector
      
    @property
    def magnitude(self) -> float:
        return self._magnitude

    @property
    def direction(self) -> np.ndarray:
        return self._direction


vec = Vector(10, 4, 2)
print(vec.vector) # [10 4 2]
print(vec.magnitude) # 10.954451150103322
print(vec.direction) # [0.91287093 0.36514837 0.18257419]
  • Related