简体   繁体   English

python中java的'constructor-overload'的等价物是什么?

[英]What is the equivalent of java's 'constructor-overload' in python?

I'm currently studying Python.我目前正在学习 Python。 I was trying to write an exercise code making a 'Line'-class with different possible input-parameters and hence different constructors, as one can do in java.我试图编写一个练习代码,使用不同的可能输入参数和不同的构造函数制作一个“Line”类,就像在 java 中所做的那样。 ie a constructor with (point,point) objects and a constructor with (point,slope) It works with both __init__ methods separately, but not with both as it does in python.即具有 (point,point) 对象的构造函数和具有 (point,slope) 的构造函数它分别与__init__方法一起使用,但不像在 python 中那样同时使用。 Could anybody help me going with this.谁能帮我解决这个问题。

class Point:
    def __init__(self,x,y):
        self.x=x
        self.y=y
    def distance_to(self,p):
        return((p1.x-p.x)**2+(p1.y-p.y)**2)**(1/2)

class Line:
    def __init__(self, p1,p2):
        self.p1=p1
        self.p2=p2
    def __init__(self,p1,a):
        self.p1=p1
        self.a=a
        b=self.p1.y-a*p1.x
        p2=Point(0,b)
        self.p2=p2             
    def slope(self):
        return (p2.y-p1.y)/(p2.x-p1.x)
    def b_intersect(self):
        b_intersect=self.p1.y-self.slope()*p1.x
    def __str__(self):       
        b_intersect=self.p1.y-self.slope()*p1.x               
        if b_intersect>0:
            return 'y={}x+{}'.format(self.slope(),b_intersect)
        elif b_intersect<0:
            return 'y={}x{}'.format(self.slope(),b_intersect)
        elif b_intersect==0:
            return 'y={}x'.format(self.slope())

You can use *kwargs in __init__ method to check what arguments you received and act accordingly.您可以在__init__方法中使用*kwargs来检查您收到的参数并相应地采取行动。 Your code modified should look like this.修改后的代码应如下所示。

class Point:
    def __init__(self,x,y):
        self.x=x
        self.y=y
    def distance_to(self,p):
        return((p1.x-p.x)**2+(p1.y-p.y)**2)**(1/2)

class Line:
    def __init__(self, p1,**kwargs):
        self.p1=p1
        if kwargs.get("p2") is not None:
            self.p2=p2
        elif kwargs.get("a")is not None:
            self.a=a
            b=self.p1.y-a*p1.x
            p2=Point(0,b)
            self.p2=p2  
        else:
           raise Exception("Did not give enough parameters")           
    def slope(self):
        return (p2.y-p1.y)/(p2.x-p1.x)
    def b_intersect(self):
        b_intersect=self.p1.y-self.slope()*p1.x
    def __str__(self):       
        b_intersect=self.p1.y-self.slope()*p1.x               
        if b_intersect>0:
            return 'y={}x+{}'.format(self.slope(),b_intersect)
        elif b_intersect<0:
            return 'y={}x{}'.format(self.slope(),b_intersect)
        elif b_intersect==0:
            return 'y={}x'.format(self.slope())

In Python, it's customary to write __init__ as the low-level initializer, which can also double as the primary "constructor".在 Python 中,习惯__init__编写为低级初始化程序,它也可以兼作主要的“构造函数”。 Additional constructors are defined as class methods.额外的构造函数被定义为类方法。

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

    @classmethod
    def from_point_slope(cls, p1, a):
        b = self.p1.y - a * p1.x
        p2 = Point(0, b)
        return cls(p1, p2)

   # ...

Now Line has two constructors:现在Line有两个构造函数:

  1. Line.__new__ takes two Point objects. Line.__new__需要两个Point对象。 (It's rare to actually override __new__ ; the default of calling the parent's __new__ and using __init__ on the result is nearly always sufficient.) (实际上很少覆盖__new__ ;调用父对象的__new__并在结果上使用__init__的默认值几乎总是足够的。)

  2. Line.from_point_slope takes a Point object and a slope. Line.from_point_slope接受一个Point对象和一个斜率。 It calculates a second point on the line from the first Point and the slope, then pass them to Line.__new__ to create the new Line .它从第一个Point和斜率计算线上的第二个点,然后将它们传递给Line.__new__以创建新Line

Both constructors use Line.__init__ to actually set the two attributes p1 and p2 .两个构造函数都使用Line.__init__来实际设置两个属性p1p2

In the future, if you think of more ways to define a line (for example, as the intersection of two planes), you simply define new class methods, rather than complicating __init__ further.以后,如果您想到更多定义线的方法(例如,作为两个平面的交点),您只需定义新的类方法,而不是进一步复杂化__init__

IMHO there are two rather simple ways to allow more than one construction syntax in Python.恕我直言,有两种相当简单的方法可以在 Python 中允许不止一种构造语法。

Assuming that you are trying to mimic the following pair of constructors in Java:假设您正在尝试在 Java 中模拟以下一对构造函数:

class Line {
    public Line(Point p1, Point p2) {
        ...
    }
    public Line(Point p1, float a) {
        ...
    }
    ...
}
  1. The parameter type test (for the simplest use cases):参数类型测试(对于最简单的用例):

     class Line: def __init__(self, p1, p2): if isinstance(p2, Point): # ok, initialize the Line object from 2 points ... else: slope = p2 # ok, initialize the line object from 1 point and 1 float ...
  2. The parameter name test for more complex use cases:更复杂用例的参数名称测试:

     class Line: def __init__(self, p1, p2=None, slope=None): # test whether syntax is Ok (optional) if (p2 is None and slope is None) or (p2 is not None and slope is not None): raise ValueError("Either p2 or slope must be given") if slope is None: # ok, initialize the Line object from 2 points p1 and p2 ... else: # ok, initialize the line object from p1 and slope ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM