<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def check_param(param, param_name, dtype, constraint=None, iterable=True, max_depth=2):
 """ checks the dtype of a parameter, and whether it satisfies a numerical contraint Parameters --------- param : object param_name : str, name of the parameter dtype : str, desired dtype of the parameter contraint : str, default: None numerical constraint of the parameter. if None, no constraint is enforced iterable : bool, default: True whether to allow iterable param max_depth : int, default: 2 maximum nesting of the iterable. only used if iterable == True Returns ------- list of validated and converted parameter(s) """

    msg = []
    msg.append(param_name + " must be "+ dtype)
    if iterable:
        msg.append(" or nested iterable of depth " + str(max_depth) +
                   " containing " + dtype + "s")

    msg.append(", but found " + param_name + " = {}".format(repr(param)))

    if constraint is not None:
        msg = (" " + constraint).join(msg)
    else:
        msg = ''.join(msg)

    # check param is numerical
    try:
        param_dt = np.array(flatten(param))# + np.zeros_like(flatten(param), dtype='int')
        # param_dt = np.array(param).astype(dtype)
    except (ValueError, TypeError):
        raise TypeError(msg)

    # check iterable
    if iterable:
        if check_iterable_depth(param) > max_depth:
            raise TypeError(msg)
    if (not iterable) and isiterable(param):
        raise TypeError(msg)

    # check param is correct dtype
    if not (param_dt == np.array(flatten(param)).astype(float)).all():
        raise TypeError(msg)

    # check constraint
    if constraint is not None:
        if not (eval('np.' + repr(param_dt) + constraint)).all():
            raise ValueError(msg)

    return param