<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def split_in_blocks(sequence, hint, weight=lambda item: 1, key=nokey):
 """ Split the `sequence` in a number of WeightedSequences close to `hint`. :param sequence: a finite sequence of items :param hint: an integer suggesting the number of subsequences to generate :param weight: a function returning the weigth of a given item :param key: a function returning the key of a given item The WeightedSequences are of homogeneous key and they try to be balanced in weight. For instance [<WeightedSequence ['A', 'B'], weight=2>, <WeightedSequence ['C', 'D'], weight=2>, <WeightedSequence ['E'], weight=1>] """

    if isinstance(sequence, int):
        return split_in_slices(sequence, hint)
    elif hint in (0, 1) and key is nokey:  # do not split
        return [sequence]
    elif hint in (0, 1):  # split by key
        blocks = []
        for k, group in groupby(sequence, key).items():
            blocks.append(group)
        return blocks
    items = sorted(sequence, key=lambda item: (key(item), weight(item)))
    assert hint > 0, hint
    assert len(items) > 0, len(items)
    total_weight = float(sum(weight(item) for item in items))
    return block_splitter(items, math.ceil(total_weight / hint), weight, key)