docs: def __param_inheritance(mcs,param_name,param):
          """
          Look for Parameter values in superclasses of this
          Parameterized class.
  
          Ordinarily, when a Python object is instantiated, attributes
          not given values in the constructor will inherit the value
          given in the object's class, or in its superclasses.  For
          Parameters owned by Parameterized classes, we have implemented
          an additional level of default lookup, should this ordinary
          lookup return only None.
  
          In such a case, i.e. when no non-None value was found for a
          Parameter by the usual inheritance mechanisms, we explicitly
          look for Parameters with the same name in superclasses of this
          Parameterized class, and use the first such value that we
          find.
  
          The goal is to be able to set the default value (or other
          slots) of a Parameter within a Parameterized class, just as we
          can set values for non-Parameter objects in Parameterized
          classes, and have the values inherited through the
          Parameterized hierarchy as usual.
  
          Note that instantiate is handled differently: if there is a
          parameter with the same name in one of the superclasses with
          instantiate set to True, this parameter will inherit
          instatiate=True.
          """
          # get all relevant slots (i.e. slots defined in all
          # superclasses of this parameter)
          slots = {}
          for p_class in classlist(type(param))[1::]:
              slots.update(dict.fromkeys(p_class.__slots__))
  
  
          # note for some eventual future: python 3.6+ descriptors grew
          # __set_name__, which could replace this and _set_names
          setattr(param,'owner',mcs)
          del slots['owner']
  
          # backwards compatibility (see Composite parameter)
          if 'objtype' in slots:
              setattr(param,'objtype',mcs)
              del slots['objtype']
  
          # instantiate is handled specially
          for superclass in classlist(mcs)[::-1]:
              super_param = superclass.__dict__.get(param_name)
              if isinstance(super_param, Parameter) and super_param.instantiate is True:
                  param.instantiate=True
          del slots['instantiate']
  
  
          for slot in slots.keys():
              superclasses = iter(classlist(mcs)[::-1])
  
              # Search up the hierarchy until param.slot (which has to
              # be obtained using getattr(param,slot)) is not None, or
              # we run out of classes to search.
              while getattr(param,slot) is None:
                  try:
                      param_super_class = next(superclasses)
                  except StopIteration:
                      break
  
                  new_param = param_super_class.__dict__.get(param_name)
                  if new_param is not None and hasattr(new_param,slot):
                      # (slot might not be there because could be a more
                      # general type of Parameter)
                      new_value = getattr(new_param,slot)
                      setattr(param,slot,new_value)