code: def train(self, scale, aesthetic=None):
          
          if aesthetic is None:
              aesthetic = scale.aesthetics[0]
  
          breaks = scale.get_breaks()
          if isinstance(breaks, OrderedDict):
              if all([np.isnan(x) for x in breaks.values()]):
                  return None
          elif not len(breaks) or all(np.isnan(breaks)):
              return None
  
          with suppress(AttributeError):
              breaks = list(breaks.keys())
  
          key = pd.DataFrame({
              aesthetic: scale.map(breaks),
              'label': scale.get_labels(breaks)})
          # Drop out-of-range values for continuous scale
          # (should use scale$oob?)
  
          # Currently, numpy does not deal with NA (Not available)
          # When they are introduced, the block below should be
          # adjusted likewise, see ggplot2, guide-lengend.r
          if isinstance(scale, scale_continuous):
              limits = scale.limits
              b = np.asarray(breaks)
              noob = np.logical_and(limits[0] <= b,
                                    b <= limits[1])
              key = key[noob]
  
          if len(key) == 0:
              return None
  
          self.key = key
  
          # create a hash of the important information in the guide
          labels = ' '.join(str(x) for x in self.key['label'])
          info = '\n'.join([self.title, labels, str(self.direction),
                            self.__class__.__name__])
          self.hash = hashlib.md5(info.encode('utf-8')).hexdigest()
          return self
docs: Create the key for the guide
  
          The key is a dataframe with two columns:
              - scale name : values
              - label : labels for each value
  
          scale name is one of the aesthetics
          ['x', 'y', 'color', 'fill', 'size', 'shape', 'alpha',
           'stroke']
  
          Returns this guide if training is successful and None
          if it fails