类的构造函数能否返回Python中的另一个类?

类的构造函数能否返回Python中的另一个类?,python,oop,Python,Oop,我现在正在玩2D几何。我创建了两个类:Point和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 一个有趣的例子是

我现在正在玩2D几何。我创建了两个类:
Point
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
一个有趣的例子是
线段(p1,p1)
——因此线段长度为零。从本质上讲,这只是点
p1
。但它的类型为
线段

我可能会使用类似以下的方法来处理该案例:

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

尽管这可能是一个非常糟糕的主意,但我仍然很好奇:是否可以让类
LineSegment
的构造函数返回类
Point
的对象?
是的,尽管不是构造函数
\uu init\uuuu()
,而是实例化器

类线段:
定义新(cls,p1:点,p2:点):
#在这里使用“是”,因为点是可变的,但这只是个人偏好
如果p1是p2:
返回p1
返回super()
定义初始(self,p1:Point,p2:Point):
self.p1=p1
self.p2=p2
a=点(0,0)
b=点(1,1)
打印(线段(a,b))#
打印(线段(a,a))#
注意,从

如果
\uuuu new\uuuuuuuuuuuuuuu()
未返回cls实例,则不会调用新实例的
\uuuuuuuuuuu init\uuuuuuuuuuuuuu()
方法


构造函数返回另一个类的实例?不可以,但您可以重写_new _方法。您可以创建一个函数“makeLineSegment()”,该函数检测特殊情况并返回正确的实例。
\u_new
需要从同一类返回对象,
忽略返回值。其他常规方法可以返回它们想要的任何内容。就像一个返回点对象的方法
to_Point(self)
一样,
\uuuu new\uuuu
实际上并不一定要返回点对象,但是Python文档中的注意:如果
\uu new\uuuuuuuuuuuuuuu()
没有返回cls的实例,那么新实例的
\uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuo()
方法将不会被调用。我对OOP没有太深的了解,所以我不知道它是不是一个好主意,但它肯定感觉不对;根据
LineSegment
实例的使用方式,可能会有一个参数用于保持退化线段与其单点之间的区别。
p1是p2
并不理想,因为这样简化对
线段(点(0,0)、点(0,0))
不起作用,退化线段是一个点,无论每个参数中是否有相同的Python对象表示该点。我想我的立场是:返回与
\uuuu new\uuuu
不同类型的对象没有问题,只要这样做是有意义的。在什么情况下它才有意义是一个完全不同的问题。在这种情况下,我想我会选择
=
,因为不应该有任何理由区分代表同一点的两个
对象。
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 ...>