在 python 中实现多个构造函数的最佳实践
Best practice to implement multiple constructors in python
我很确定这个问题已经被问过很多次了,但我仍然不确定如何在 Python 中实现多个构造函数。我知道在 python 中,我只能有一个构造函数,这与 java 或 C# 或 C++ 不同。我对它还是很陌生。长话短说,我需要实现一个线对象。该线将由函数 y = ax + b 表示。因此,我唯一需要存储在行中的是 a、b 和一个布尔值,用于行是垂直的特殊情况(a = 无穷大)。在这种情况下,a 将存储该行的 x 位置。要创建一条线,我有 3 种方法。 1是直接把a,b和boolean放进去。 2是以元组的形式放入2个点。 3是放入一个点和一个向量。到目前为止我的代码:
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)
不确定是否有更好的方法
您可以使用默认值 None:
创建一个包含所有必需参数的构造函数
class line:
def __init__(self, a = None, b = None, noSlope = None, point1 = None, point2 = None, vector = None, point = None):
pass
然后您将检查在构造函数中传递了哪些参数并根据这些参数创建行。
更新:
使用 @classmethod
.
的 @classmethod
, as suggested by Jim. Raymond Hettinger did a talk on Python's class development toolkit at Pycon 2013, where he talked about multiple constructors 实现多个构造函数的更 pythonic 方式
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
,@classmethod
函数的cls
参数作为调用class隐式传递(在上面的示例中,它是Line
).这用于使用额外的构造函数来容纳未来的 subclasses;它通过硬编码基础 class 代替 cls
.
来消除意外绕过子 class 的构造函数实现的潜在错误
原创 POST:
如果你想强制使用你的构造函数,你可以让它们 static methods,并让它们 return 成为你的 class.
的一个实例
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__
,你可以使用以下工厂来隐藏 Line class:
的直接实例化
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))
您可以使用 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)
我很确定这个问题已经被问过很多次了,但我仍然不确定如何在 Python 中实现多个构造函数。我知道在 python 中,我只能有一个构造函数,这与 java 或 C# 或 C++ 不同。我对它还是很陌生。长话短说,我需要实现一个线对象。该线将由函数 y = ax + b 表示。因此,我唯一需要存储在行中的是 a、b 和一个布尔值,用于行是垂直的特殊情况(a = 无穷大)。在这种情况下,a 将存储该行的 x 位置。要创建一条线,我有 3 种方法。 1是直接把a,b和boolean放进去。 2是以元组的形式放入2个点。 3是放入一个点和一个向量。到目前为止我的代码:
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)
不确定是否有更好的方法
您可以使用默认值 None:
创建一个包含所有必需参数的构造函数class line:
def __init__(self, a = None, b = None, noSlope = None, point1 = None, point2 = None, vector = None, point = None):
pass
然后您将检查在构造函数中传递了哪些参数并根据这些参数创建行。
更新:
使用 @classmethod
.
@classmethod
, as suggested by Jim. Raymond Hettinger did a talk on Python's class development toolkit at Pycon 2013, where he talked about multiple constructors 实现多个构造函数的更 pythonic 方式
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
,@classmethod
函数的cls
参数作为调用class隐式传递(在上面的示例中,它是Line
).这用于使用额外的构造函数来容纳未来的 subclasses;它通过硬编码基础 class 代替 cls
.
原创 POST:
如果你想强制使用你的构造函数,你可以让它们 static methods,并让它们 return 成为你的 class.
的一个实例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__
,你可以使用以下工厂来隐藏 Line class:
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))
您可以使用 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)