2016-03-27 3 views
1

Я уверен, что это было задано много раз, но я все еще не уверен, как реализовать множественные конструкторы в Python. Я знаю, что в python у меня может быть только один конструктор, отличный от java или C# или C++. Я до сих пор довольно новичок в этом. Короче говоря, мне нужно реализовать объект линии. Линия будет представлена ​​функцией y = ax + b. Поэтому единственное, что мне нужно сохранить в строке, это a, b и boolean для специального случая, когда линия вертикальна (a = бесконечность). В этом случае a сохранит положение x линии. Чтобы создать строку, у меня есть 3 способа. 1 - непосредственно вставить a, b и boolean. 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

Как это питон вопрос, пожалуйста, удалите C# и С ++ тегов, как это не имеет ничего общего с вашей проблемой – BugFinder

+0

Спасибо.Я просто сделал –

+0

Не уверен, что вы просите конкретно, и конструктор выглядит так, как есть, но несколько вещей, которые выделяются - имена классов всегда заглавные, поэтому назовите его 'class Line:'. Кроме того, для всех этих поисков индекса ('point1 [0]' и т. Д.) Вы можете сказать 'x1, y1 = point1' и' x2, y2 = point2', а затем ваш 'deltaX' может быть просто' x2-x1' и позже вы можете повторно использовать 'x1, x2, y1, y2' и т. д. В основном думайте о своих обозначениях, как бы я это сделал, если бы я пытался решить какое-то подобное математическое уравнение на бумаге. – Bahrom

ответ

5

UPDATE:

Чем больше вещий способ сделать несколько конструкторов с @classmethod, как это было предложено Jim. Раймонд Хеттингер выступил с докладом о наборе инструментов для разработки классов Python на Pycon 2013, где он рассказал о multiple constructors, используя @classmethod.

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)) 

EDIT:
Если вы хотите, чтобы использовать ваши конструкторы над использованием Line.__init__, вы можете использовать следующую фабрику, чтобы скрыть прямую экземпляра класса Line:

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

Вы можете создать один конструктор со всеми необходимыми параметрами со значением по умолчанию None:

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

Это интересный способ сделать это. хммм .. –

Смежные вопросы