As an alternative, I would do it using class methods, so the constructor would only take fields as arguments.
class Vector(object):
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return 'Vector({}, {})'.format(self.x, self.y)
@classmethod
def polarVector(cls, angle, mag):
return cls(math.cos(angle) * mag, math.sin(angle) * mag)
@classmethod
def magVector(cls, x, y, mag):
a = mag / math.sqrt(x**2 + y**2)
return cls(x * a, y * a)
Problems with optional arguments
The major problem with optional arguments is code clarity.
a = Vector(1, 2) # Is 1 "angle" or "x"?
a = Vector(3, 4, 10) # Huh?
# These functions do different things,
# so it makes sense that they have different names.
a = Vector.polarVector(1, 2)
a = Vector.magVector(3, 4, 10)