2016-03-27 54 views
1

我非常肯定这已经被问了很多次,但我仍然不确定如何在Python中实现多个构造函数。我知道在python中,我只能有一个不同于java或C#或C++的构造函数。我对它仍然很陌生。长话短说,我需要实现一个线对象。该行将由函数y = ax + b表示。所以我需要在行中存储的唯一东西是a,b和布尔值,用于垂直线(a =无穷大)的特殊情况。在这种情况下,a将存储该行的x位置。为了创建一条线,我有3种方法。 1是直接放入a,b和布尔值。 2是以元组的形式放2分。 3是放在一个点和一个向量。到目前为止我的代码:在python中实现多个构造函数的最佳实践

class line: 
    def __init__(self, a, b, noSlope): 
     self.a = a 
     self.b = b 
     self.noSlope = noSlope 

    def lineFromPoints(point1, point2): 
     deltaX = point2[0] - point1[0] 
     deltaY = point2[1] - point1[1] 
     if deltaX == 0: 
      return line(point1[0], 0, True) 
     else: 
      a = deltaY/deltaX 
      b = point1[1] - a * point1[0] 
      return line(a, b, False) 

    def lineFromVector(vector, point): 
     if vector[0] == 0: 
      return line(point1[0], 0, True) 
     else: 
      a = vector[1]/vector[0] 
      b = point1[1] - a * point1[0] 
      return line(a, b, False) 

不知道是否有更好的方法来做到这一点

+0

由于这是一个Python问题,请删除C#和C++代码,因为它无关,与你的问题 – BugFinder

+0

谢谢。我只是做了 –

+0

不知道你在问什么具体问题,而且构造函数看起来很好,但是有一些非常突出的东西 - 类名总是大写,所以称之为'class Line:'。对于所有这些索引查找('point1 [0]'等),你可以说'x1,y1 = point1'和'x2,y2 = point2',然后你的'deltaX'可以只是'x2-x1'后来你可以重复使用'x1,x2,y1,y2'等。基本上把你的符号想象成如果我试图在纸上解决一些相似的数学方程,我该如何做到这一点。 – Bahrom

回答

5

UPDATE:

做多个构造的更多Python的方式是@classmethod,由Jim的建议。 Raymond Hettinger在Pycon 2013上就Python的班级开发工具包进行了演讲,在那里他使用@classmethod谈论了multiple constructors

class Line: 
    def __init__(self, a, b, noSlope): 
     self.a = a 
     self.b = b 
     self.noSlope = noSlope 

    @classmethod 
    def fromPoints(cls, point1, point2): 
     deltaX = point2[0] - point1[0] 
     deltaY = point2[1] - point1[1] 
     if deltaX == 0: 
      return cls(point1[0], 0, True) 
     else: 
      a = deltaY/deltaX 
      b = point1[1] - a * point1[0] 
      return cls(a, b, False) 

    @classmethod 
    def fromVector(cls, vector, point): 
     if vector[0] == 0: 
      return cls(point1[0], 0, True) 
     else: 
      a = vector[1]/vector[0] 
      b = point1[1] - a * point1[0] 
      return cls(a, b, False) 


line = Line.fromPoints((0,0), (1,1)) 

self类似,cls参数为@classmethod用作调用类隐式传递(在上面的例子中,这将是Line)。这用于使用其他构造函数来适应未来的子类;它通过硬编码基类来代替cls,从而避免了意外绕过子类实现构造函数的潜在错误。


原贴:

如果要强制使用您的构造函数,你可以让他们static methods,并让他们回到你的类的实例。

class line: 
    def __init__(self, a, b, noSlope): 
     self.a = a 
     self.b = b 
     self.noSlope = noSlope 

    @staticmethod 
    def lineFromPoints(point1, point2): 
     deltaX = point2[0] - point1[0] 
     deltaY = point2[1] - point1[1] 
     if deltaX == 0: 
      return line(point1[0], 0, True) 
     else: 
      a = deltaY/deltaX 
      b = point1[1] - a * point1[0] 
      return line(a, b, False) 

    @staticmethod 
    def lineFromVector(vector, point): 
     if vector[0] == 0: 
      return line(point1[0], 0, True) 
     else: 
      a = vector[1]/vector[0] 
      b = point1[1] - a * point1[0] 
      return line(a, b, False) 

# Create instance of class 
myLine = line.lineFromPoints((0,0), (1,1)) 

编辑:
如果要强制使用您的构造函数在使用Line.__init__,您可以使用下面的工厂隐藏线类直接实例:

class LineFactory: 
    class Line: 
     def __init__(self, a, b, noSlope): 
      self.a = a 
      self.b = b 
      self.noSlope = noSlope 

    @staticmethod 
    def fromPoints(point1, point2): 
     deltaX = point2[0] - point1[0] 
     deltaY = point2[1] - point1[1] 
     if deltaX == 0: 
      return LineFactory.Line(point1[0], 0, True) 
     else: 
      a = deltaY/deltaX 
      b = point1[1] - a * point1[0] 
      return LineFactory.Line(a, b, False) 

    @staticmethod 
    def fromVector(vector, point): 
     if vector[0] == 0: 
      return LineFactory.Line(point1[0], 0, True) 
     else: 
      a = vector[1]/vector[0] 
      b = point1[1] - a * point1[0] 
      return LineFactory.Line(a, b, False) 

# Create line  
line = LineFactory.fromPoints((0,0), (1,1)) 
+0

我正要编辑我的评论并提出静态方法,这是一个很好的方法。你也可以大写类名(只是一个建议) – Bahrom

+0

我建议大写这个名字! – sdsmith

+0

问题:现在是否仍然可以使用Line类,因为它被包含在LineFactory类中? –

0

您可以创建一个构造函数所需的所有参数的默认值无:

class line: 
    def __init__(self, a = None, b = None, noSlope = None, point1 = None, point2 = None, vector = None, point = None): 
     pass 

然后你会检查哪些paameters在构造函数中传递并从这些参数创建行。

0

你可以使用Pyhton的枚举来声明初始化方法如下:

from enum import Enum 

class Line: 

    class InitTypes(Enum): 
     coefs, point_vector, point_point, vertical = range(4) 


    def __init__(self, a, b, method): 
     self.noSlope = False 
     if method == Line.InitTypes.coefs: 
      self.a = a 
      self.b = b 
     elif method == Line.InitTypes.point_vector: 
      # Do math 
      pass 
     elif method == Line.InitTypes.point_point: 
      # Do math 
      pass 
     elif method == Line.InitTypes.vertical: 
      self.noSlope = True 
      self.a = a 
      self.b = b 
     else: 
      assert(False) 

然后,创建一个如下所示的行:

x = Line((0,1), (3,4), Line.InitTypes.point_point) 
+0

这是一个有趣的方式来做到这一点。 hmmmm .. –