Performs a breadth-first search of a graph-like structure.

    :param start: Node to start the search from
    :param expand: Function taking a node as an argument and returning iterable
                   of its child nodes

    :return: Iterable of nodes in the BFS order

    Example::

        tree = json.loads(some_data)
        for item in breadth_first(tree, key_func('children', default=())):
            do_something_with(item)

def breadth_first(start, expand):
    """Performs a breadth-first search of a graph-like structure.

    :param start: Node to start the search from
    :param expand: Function taking a node as an argument and returning iterable
                   of its child nodes

    :return: Iterable of nodes in the BFS order

    Example::

        tree = json.loads(some_data)
        for item in breadth_first(tree, key_func('children', default=())):
            do_something_with(item)
    """
    ensure_callable(expand)

    def generator():
        queue = deque([start])
        while queue:
            node = queue.popleft()
            yield node
            queue.extend(expand(node))

    return generator()