def print_tree(
        expr, attr='operands', padding='', exclude_type=None, depth=None,
        unicode=True, srepr_leaves=False, _last=False, _root=True, _level=0,
        _print=True):
    """Print a tree representation of the structure of `expr`

    Args:
        expr (Expression): expression to render
        attr (str): The attribute from which to get the children of `expr`
        padding (str): Whitespace by which the entire tree is idented
        exclude_type (type): Type (or list of types) which should never be
            expanded recursively
        depth (int or None): Maximum depth of the tree to be printed
        unicode (bool): If True, use unicode line-drawing symbols for the tree,
            and print expressions in a unicode representation.
            If False, use an ASCII approximation.
        srepr_leaves (bool): Whether or not to render leaves with `srepr`,
            instead of `ascii`/`unicode`

    See also:
        :func:`tree` return the result as a string, instead of printing it
    """
    from qnet.printing import srepr
    lines = []
    if unicode:
        draw = {'leaf': '└─ ', 'branch': '├─ ', 'line': '│'}
        sub_render = _shorten_render_unicode()
    else:
        draw = {'leaf': '+- ', 'branch': '+- ', 'line': '|'}
        sub_render = _shorten_render_ascii()
    to_str = lambda expr: render_head_repr(
            expr, sub_render=sub_render, key_sub_render=sub_render)
    if _root:
        lines.append(". " + to_str(expr))
    else:
        if _last:
            lines.append(padding[:-1] + draw['leaf'] + to_str(expr))
        else:
            lines.append(padding[:-1] + draw['branch'] + to_str(expr))
    padding = padding + '  '
    try:
        children = getattr(expr, attr)
    except AttributeError:
        children = []
    if exclude_type is not None:
        if isinstance(expr, exclude_type):
            children = []
    if depth is not None:
        if depth <= _level:
            children = []
    for count, child in enumerate(children):
        if hasattr(child, attr):
            if count == len(children)-1:
                lines += print_tree(
                    child, attr, padding + ' ',
                    exclude_type=exclude_type, depth=depth, unicode=unicode,
                    srepr_leaves=srepr_leaves, _last=True, _root=False,
                    _level=_level+1)
            else:
                lines += print_tree(
                    child, attr, padding + draw['line'],
                    exclude_type=exclude_type, depth=depth, unicode=unicode,
                    srepr_leaves=srepr_leaves, _last=False, _root=False,
                    _level=_level+1)
        else:
            if count == len(children)-1:
                if srepr_leaves:
                    lines.append(padding + draw['leaf'] + srepr(child))
                else:
                    lines.append(padding + draw['leaf'] + to_str(child))
            else:
                if srepr_leaves:
                    lines.append(padding + draw['branch'] + srepr(child))
                else:
                    lines.append(padding + draw['branch'] + to_str(child))
    if _root:
        if _print:
            print("\n".join(lines))
        else:
            return lines
    else:
        return lines