def edit_files(patterns, expressions=None,
               functions=None, executables=None,
               start_dirs=None, max_depth=1, dry_run=True,
               output=sys.stdout, encoding=None, newline=None):
    if not is_list(patterns):
        raise TypeError("patterns should be a list")
    if expressions and not is_list(expressions):
        raise TypeError("expressions should be a list of exec expressions")
    if functions and not is_list(functions):
        raise TypeError("functions should be a list of functions")
    if executables and not is_list(executables):
        raise TypeError("executables should be a list of program names")
    editor = MassEdit(dry_run=dry_run, encoding=encoding, newline=newline)
    if expressions:
        editor.set_code_exprs(expressions)
    if functions:
        editor.set_functions(functions)
    if executables:
        editor.set_executables(executables)
    processed_paths = []
    for path in get_paths(patterns, start_dirs=start_dirs,
                          max_depth=max_depth):
        try:
            diffs = list(editor.edit_file(path))
            if dry_run:
                diff = "".join(diffs)
                if not diff:
                    continue
                encoding = output.encoding
                if encoding:
                    bytes_diff = diff.encode(encoding=encoding, errors='ignore')
                    diff = bytes_diff.decode(encoding=output.encoding)
                output.write(diff)
        except UnicodeDecodeError as err:
            log.error("failed to process %s: %s", path, err)
            continue
        processed_paths.append(os.path.abspath(path))
    return processed_paths