Search code examples
pythonoop

Can the constructor of a class return another class in Python?


I'm currently playing around with 2D geometry. I created two classes: Point and LineSegment:

class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

class LineSegment:
    def __init__(self, p1: Point, p2: Point):
        self.p1 = p1
        self.p2 = p2

An interesting case is LineSegment(p1, p1) - hence a line segment of length zero. Essentially, this is just the point p1. But it is of type LineSegment.

I will likely use something like the following to deal with that case:

class LineSegment:
    def __init__(self, p1: Point, p2: Point):
        self.p1 = p1
        self.p2 = p2

    def simplify(self):
        if self.p1 == self.p2:
            return self.p1
        return self

Although it is likely a very bad idea, I'm still curious: Is it possible to make the constructor of class LineSegment return an object of class Point?


Solution

  • Yes, using __new__().

    class LineSegment:
        def __new__(cls, p1: Point, p2: Point):
            # Using "is" here since Points are mutable, but that's just personal preference
            if p1 is p2:
                return p1
            return super().__new__(cls)
    
        def __init__(self, p1: Point, p2: Point):
            self.p1 = p1
            self.p2 = p2
    
    a = Point(0, 0)
    b = Point(1, 1)
    print(LineSegment(a, b))  # <__main__.LineSegment object at ...>
    print(LineSegment(a, a))  # <__main__.Point object at ...>
    

    Note, from the docs

    If __new__() does not return an instance of cls, then the new instance’s __init__() method will not be invoked.