import types


def copy_func(f, name=None):
    """ Returns a function with the same code, globals, defaults, closure, and name (unless provided a different name).
    """
    fn = types.FunctionType(f.__code__,
                            f.__globals__, name or f.__name__,
                            f.__defaults__,
                            f.__closure__)
    fn.__dict__.update(f.__dict__)
    return fn