from dataclasses import dataclass @dataclass class Product: price: float # with none @dataclass class DiscountCoupon: rate: float @dataclass class Cart: products: list[Product] discount_coupon: DiscountCoupon def subtotal(self): return sum(product.price for product in self.products) def total(self): if self.discount_coupon is None: return self.subtotal() else: return self.subtotal() * (1 - self.discount_coupon.rate) cart = Cart([Product(10.12), Product(3.78)], DiscountCoupon(0.15)) print(cart.total()) # 11.814999999999998 cart = Cart([Product(10.12), Product(3.78)], None) print(cart.total()) # 13.899999999999999 # with NullObject @dataclass class DiscountCoupon: rate: float def discount(self, subtotal): return subtotal * (1 - self.rate) @dataclass class NullDiscountCoupon: def discount(self, subtotal): return subtotal @dataclass class Cart: products: list[Product] discount_coupon: DiscountCoupon def subtotal(self): return sum(product.price for product in self.products) def total(self): return self.discount_coupon.discount(self.subtotal()) cart = Cart([Product(10.12), Product(3.78)], DiscountCoupon(0.15)) print(cart.total()) # 11.814999999999998 cart = Cart([Product(10.12), Product(3.78)], NullDiscountCoupon()) print(cart.total()) # 13.899999999999999