<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def construct(parent=None, defaults=None, **kwargs):
 """ Random variable constructor. Args: cdf: Cumulative distribution function. Optional if ``parent`` is used. bnd: Boundary interval. Optional if ``parent`` is used. parent (Dist):
 Distribution used as basis for new distribution. Any other argument that is omitted will instead take is function from ``parent``. doc (str]):
 Documentation for the distribution. str (str, :py:data:typing.Callable):
 Pretty print of the variable. pdf: Probability density function. ppf: Point percentile function. mom: Raw moment generator. ttr: Three terms recursion coefficient generator. init: Custom initialiser method. defaults (dict):
 Default values to provide to initialiser. Returns: (Dist):
 New custom distribution. """

    for key in kwargs:
        assert key in LEGAL_ATTRS, "{} is not legal input".format(key)

    if parent is not None:
        for key, value in LEGAL_ATTRS.items():
            if key not in kwargs and hasattr(parent, value):
                    kwargs[key] = getattr(parent, value)

    assert "cdf" in kwargs, "cdf function must be defined"
    assert "bnd" in kwargs, "bnd function must be defined"
    if "str" in kwargs and isinstance(kwargs["str"], str):
        string = kwargs.pop("str")
        kwargs["str"] = lambda *args, **kwargs: string

    defaults = defaults if defaults else {}
    for key in defaults:
        assert key in LEGAL_ATTRS, "invalid default value {}".format(key)

    def custom_distribution(**kws):

        prm = defaults.copy()
        prm.update(kws)
        dist = Dist(**prm)

        for key, function in kwargs.items():
            attr_name = LEGAL_ATTRS[key]
            setattr(dist, attr_name, types.MethodType(function, dist))
        return dist

    if "doc" in kwargs:
        custom_distribution.__doc__ = kwargs["doc"]

    return custom_distribution