0

How can I control type casting for my classes? I know there is __int__() or __str__(), but what about other types? E.g. I have two classes Point and Vector. Is it possible to do something like:

point = Point(1, 2, 3)

# the following should not call Vector._init_(), but use a cast defined in Point
# (something like Point.__Vector__())
vector = Vector(point)

Is this possible? If so, how can I achieve such behavior? If not, for what standard types could I define a cast function to allow e.g. tuple(point) or list(point) - couldn't find this in the python documentation.

Smack Alpha
  • 1,828
  • 1
  • 17
  • 37
natter1
  • 354
  • 2
  • 10
  • See the second answer to this ? https://stackoverflow.com/questions/31446603/how-to-make-type-cast-for-python-custom-class – Dese Oct 18 '19 at 12:44
  • @Dese Not exactly what I want. But reading it, I stumbled about a list in the python docu -I guess casting is only supported with build in functions for int float and complex, not even for list etc. In that case I have to stick to methods, to achieve type conversion (like Point.getVector() or Point.getList()) – natter1 Oct 18 '19 at 12:57
  • You could modify `Vector.__init___` to see if an object of specific type (e.g. `Point`) was passed and proceed accordingly. – gstukelj Oct 18 '19 at 13:25
  • "casting" isn't really a distinct thing, in each case, you are simply passing objects to constructors. The built-in types use hooks that are part of the Python data model, but there is nothing preventing you from implementing an `__init__` in `Vector` that accepts a `Point` type – juanpa.arrivillaga Oct 18 '19 at 15:29
  • @juanpa.arrivillaga the "difference" would be, were the conversion happens. Doing it in \_\_init__ would require Vector to know about all usecases and handle them. On the other hand e.g. \_\_str__() allows me to handle it in a class like Point - without a need for string to know about Point. But I guess "casting" is not very "pythonian", otherwse I would have easily found examples. So I will stick with explicit methods (as long as nobody points out why a different approach would be more pythonian). – natter1 Oct 18 '19 at 15:40
  • 1
    @natter1 again, you are *free to implement* your constructor however you want. If you want to expose a hook, merely document it, and your `Vector.__init__` can try to call a `obj.to_vector` method, there is nothing distinct there compared to the built-in types, simply, the hook is not part of the data model. "Casting" is not really a useful concept in a purely object-oriented, dynamically typed language like Python. Constructors accept objects and return objects of that given type. – juanpa.arrivillaga Oct 18 '19 at 15:58
  • @juanpa.arrivillaga - you are right, I didn't think about using the hook inside Vector.\_\_init__ I will try that one. – natter1 Oct 18 '19 at 16:42

1 Answers1

0

You could do it via the use of classmethods.

For example,

from point import Point  # where the Point object is defined

class Vector:
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

    @classmethod
    def from_point(cls, point):
        if not isinstance(point, Point):  # some validation first
            raise TypeError("The given object is not of type 'Point'")
        return cls(point.x, point.y, point.z)

    # other methods

Thus, then if you have a p = Point(1, 0, 0) then you can do v = Vector.from_point(p) and you'll have what you were looking for.

There are quite some improvements that could be applied but depend on the details of Point.

Ignacio Vergara Kausel
  • 5,521
  • 4
  • 31
  • 41