How to combine the following 2 classes into one class, Rectangle, so that a Rectangle object can be created either by rect = Rectangle(side_a, side_b) or rect = Rectangle(side_a, area)?
class Rectangle1:
def __init__(self, side_a, side_b):
self.side_a = side_a
self.side_b = side_b
self.area = self.side_a * self.side_b
class Rectangle2:
def __init__(self, side_a, area):
self.side_a = side_a
self.area = area
self.side_b = self.area / side_a
As demonstrated here.
class Rectangle:
def __init__(self, a, b):
""" Create a new rectangle with sides of length a and b.
"""
self.side_a = side_a
self.side_b = side_b
self.area = self.side_a * self.side_b
@classmethod
def from_sides(cls, a, b):
return cls(a, b)
@classmethod
def from_area(cls, a, o):
return cls(a, o/a)
You can then create rectangles as
r1 = Rectangle.from_sides(s1, s2)
r2 = Rectangle.from_area(s1, a)
You cannot overload methods with methods of the same name. Well, you can, but only the last one is then visible.
The other option is keyword-only arguments.
With Python 3, you could write:
class Rectangle:
def __init__(self, side_a, *, side_b=None, area=None):
self.side_a = side_a
if side_b is None and area is None:
raise Exception("Provide either side_b or area")
if side_b is not None and area is not None:
raise Exception("Provide either side_b or area, not both")
if side_b is not None:
self.side_b = side_b
self.area = self.side_a * self.side_b
else:
self.area = area
self.side_b = self.area / side_a
using *
in the middle forces the user to use keyword argument passing from that point, not allowing positionnal, which prevents the mistakes. And the (rather clumsy) manual checking for None
logic ensures that one and only one keyword parameter is passed to the constructor. The inside is complex, but the interface is safe to use, that's the main point here.
r = Rectangle(10,area=20)
r2 = Rectangle(10,side_b=20)
r3 = Rectangle(10,20) # doesn't run, need keyword arguments
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With