docs: def param(self, pname, cname=None, history=0):
          """Get parameter from a category and history.
  
          :param str pname: parameter name.
          :param str cname: category name. Default is the last registered.
          :param int history: historical param value from specific category or
              final parameter value if cname is not given. For example, if history
              equals 1 and cname is None, result is the value defined just before
              the last parameter value if exist. If cname is given, the result
              is the parameter value defined before the category cname.
          :rtype: Parameter
          :raises: NameError if pname or cname do not exist."""
  
          result = None
  
          category = None
  
          categories = []  # list of categories containing input parameter name
  
          for cat in self.values():
  
              if pname in cat:
  
                  categories.append(cat)
  
                  if cname == cat.name:
                      break
  
          if cname is not None and (
                  not categories or categories[-1].name != cname
          ):
              raise NameError('Category {0} does not exist.'.format(cname))
  
          categories = categories[:max(1, len(categories) - history)]
  
          for category in categories:
              if pname in category:
                  if result is None:
                      result = category[pname].copy()
  
                  else:
                      result.update(category[pname])
  
          return result