Split a string based on given delimiter(s).
    Delimiters can be either strings or compiled regular expression objects.

    :param s: String to split
    :param by: A delimiter, or iterable thereof.
    :param maxsplit: Maximum number of splits to perform.
                     ``None`` means no limit,
                     while 0 does not perform a split at all.

    :return: List of words in the string ``s``
             that were separated by delimiter(s)

    :raise ValueError: If the separator is an empty string or regex

def split(s, by=None, maxsplit=None):
    """Split a string based on given delimiter(s).
    Delimiters can be either strings or compiled regular expression objects.

    :param s: String to split
    :param by: A delimiter, or iterable thereof.
    :param maxsplit: Maximum number of splits to perform.
                     ``None`` means no limit,
                     while 0 does not perform a split at all.

    :return: List of words in the string ``s``
             that were separated by delimiter(s)

    :raise ValueError: If the separator is an empty string or regex
    """
    ensure_string(s)

    # TODO(xion): Consider introducing a case for ``split('')``
    # to make it return ``['']`` rather than default ``[]`` thru ``str.split``.
    # It's the so-called "whitespace split" that normally eliminates
    # empty strings from result. However, ``split(s)`` for any other ``s``
    # always returns ``[s]`` so these two approaches are at odds here.
    # (Possibly refer to split functions in other languages for comparison).

    # string delimiter are handled by appropriate standard function
    if by is None or is_string(by):
        return s.split(by) if maxsplit is None else s.split(by, maxsplit)

    # regex delimiters have certain special cases handled explicitly below,
    # so that we do the same things that ``str.split`` does
    if is_regex(by):
        if not by.pattern:
            return s.split('')  # will fail with proper exception & message
        if maxsplit == 0:
            return [s]
        return by.split(s, maxsplit=maxsplit or 0)

    # multiple delimiters are handled by regex that matches them all
    if is_iterable(by):
        if not by:
            raise ValueError("empty separator list")
        by = list(imap(ensure_string, by))
        if not s:
            return ['']  # quickly eliminate trivial case
        or_ = s.__class__('|')
        regex = join(or_, imap(re.escape, by))
        return split(s, by=re.compile(regex), maxsplit=maxsplit)

    raise TypeError("invalid separator")