1

I am following "Fluent Python" to learn Function and Design Pattern:

In chapter 6 example-code/strategy.py

class Order:  # the Context

    def __init__(self, customer, cart, promotion=None):
        self.customer = customer
        self.cart = list(cart)
        self.promotion = promotion

    def total(self):
        if not hasattr(self, '__total'):
            self.__total = sum(item.total() for item in self.cart)
        return self.__total

    def due(self):
        if self.promotion is None:
            discount = 0
        else:
            discount = self.promotion(self)  # <1>
        return self.total() - discount

    def __repr__(self):
        fmt = '<Order total: {:.2f} due: {:.2f}>'
        return fmt.format(self.total(), self.due())

I am very confused about:

    def total(self):
        if not hasattr(self, '__total'):
            self.__total = sum(item.total() for item in self.cart)
        return self.__total

What's the purpose of if condition here? I guess it could be more readable if:

    def total(self):
        return sum(item.total() for item in self.cart)

What's the key point I missed? could you please provide any hints?

AbstProcDo
  • 19,953
  • 19
  • 81
  • 138

1 Answers1

3

What happens if you call total more than once? If self.cart hasn't changed, then you're needlessly recalculating the total, a potentially expensive operation.

You're checking if you've already stored the value. If you haven't you calculate it, but if you have you simply return the stored value without recalculating.

As an aside, I would expect name mangling to make your life difficult here because of the double underscore at the beginning of __total. You may want to consider switching to a single underscore.

Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96