text: class Link:
      """A linked list.
  
      >>> s = Link(1)
      >>> s.first
      1
      >>> s.rest is Link.empty
      True
      >>> s = Link(2, Link(3, Link(4)))
      >>> s.second
      3
      >>> s.first = 5
      >>> s.second = 6
      >>> s.rest.rest = Link.empty
      >>> s                                    # Displays the contents of repr(s)
      Link(5, Link(6))
      >>> s.rest = Link(7, Link(Link(8, Link(9))))
      >>> s
      Link(5, Link(7, Link(Link(8, Link(9)))))
      >>> print(s)                             # Prints str(s)
      <5 7 <8 9>>
      """
      empty = ()
  
      def __init__(self, first, rest=empty):
          assert rest is Link.empty or isinstance(rest, Link)
          self.first = first
          self.rest = rest
  
      @property
      def second(self):
          return self.rest.first
  
      @second.setter
      def second(self, value):
          self.rest.first = value
  
  
      def __repr__(self):
          if self.rest is not Link.empty:
              rest_repr = ', ' + repr(self.rest)
          else:
              rest_repr = ''
          return 'Link(' + repr(self.first) + rest_repr + ')'
  
      def __str__(self):
          string = '<'
          while self.rest is not Link.empty:
              string += str(self.first) + ' '
              self = self.rest
          return string + str(self.first) + '>'
  
  def digits(n):
      """Return the digits of n as a linked list.
  
      >>> digits(0) is Link.empty
      True
      >>> digits(543)
      Link(5, Link(4, Link(3)))
      """
      # (mostly) copy-paste from Lab 7
      s = Link.empty
      while n > 0:
          n, last = n // 10, n % 10
          s = Link(last) if s is Link.empty else Link(last, s)
      return s
  
  class VendingMachine:
      """A vending machine that vends some product for some price.
  
      >>> v = VendingMachine('candy', 10)
      >>> v.vend()
      'Machine is out of stock.'
      >>> v.deposit(15)
      'Machine is out of stock. Here is your $15.'
      >>> v.restock(2)
      'Current candy stock: 2'
      >>> v.vend()
      'You must deposit $10 more.'
      >>> v.deposit(7)
      'Current balance: $7'
      >>> v.vend()
      'You must deposit $3 more.'
      >>> v.deposit(5)
      'Current balance: $12'
      >>> v.vend()
      'Here is your candy and $2 change.'
      >>> v.deposit(10)
      'Current balance: $10'
      >>> v.vend()
      'Here is your candy.'
      >>> v.deposit(15)
      'Machine is out of stock. Here is your $15.'
  
      >>> w = VendingMachine('soda', 2)
      >>> w.restock(3)
      'Current soda stock: 3'
      >>> w.restock(3)
      'Current soda stock: 6'
      >>> w.deposit(2)
      'Current balance: $2'
      >>> w.vend()
      'Here is your soda.'
      """
      def __init__(self, product, price):
          self.product = product
          self.price = price
          self.stock = 0
          self.balance = 0
  
      def restock(self, n):
          self.stock += n
          return 'Current {0} stock: {1}'.format(self.product, self.stock)
  
      def deposit(self, n):
          if self.stock == 0:
              return 'Machine is out of stock. Here is your ${0}.'.format(n)
          self.balance += n
          return 'Current balance: ${0}'.format(self.balance)
  
      def vend(self):
          if self.stock == 0:
              return 'Machine is out of stock.'
          difference = self.price - self.balance
          if difference > 0:
              return 'You must deposit ${0} more.'.format(difference)
          message = 'Here is your {0}'.format(self.product)
          if difference != 0:
              message += ' and ${0} change'.format(-difference)
          self.balance = 0
          self.stock -= 1
          return message + '.'
  
  class MissManners:
      """A container class that only forwards messages that say please.
  
      >>> v = VendingMachine('teaspoon', 10)
      >>> v.restock(2)
      'Current teaspoon stock: 2'
  
      >>> m = MissManners(v)
      >>> m.ask('vend')
      'You must learn to say please first.'
      >>> m.ask('please vend')
      'You must deposit $10 more.'
      >>> m.ask('please deposit', 20)
      'Current balance: $20'
      >>> m.ask('now will you vend?')
      'You must learn to say please first.'
      >>> m.ask('please hand over a teaspoon')
      'Thanks for asking, but I know not how to hand over a teaspoon.'
      >>> m.ask('please vend')
      'Here is your teaspoon and $10 change.'
  
      >>> double_fussy = MissManners(m) # Composed MissManners objects
      >>> double_fussy.ask('deposit', 10)
      'You must learn to say please first.'
      >>> double_fussy.ask('please deposit', 10)
      'Thanks for asking, but I know not how to deposit.'
      >>> double_fussy.ask('please please deposit', 10)
      'Thanks for asking, but I know not how to please deposit.'
      >>> double_fussy.ask('please ask', 'please deposit', 10)
      'Current balance: $10'
      """
      def __init__(self, obj):
          self.obj = obj
  
      def ask(self, message, *args):
          magic_word = 'please '
          if not message.startswith(magic_word):
              return 'You must learn to say please first.'
          else:
              # trim out the magic word
              command = message[len(magic_word)::]
              if hasattr(self.obj, command):
                  cmd_fn = getattr(self.obj, command)
                  return cmd_fn(*args)
              else:
                  return 'Thanks for asking, but I know not how to %s.' % command
  