Maybe even better, decorator and simple_decorator in one: def decorator(deco): """deco(func,func_args,func_kwargs,deco_args...) @decorator def my_deco(func,func_args,func_kwargs,deco_args...): pass @my_deco(*deco_args,**deco_kwargs) def func(*func_args,**func_kwargs): pass @decorator def my_deco2(func,func_args,func_kwargs): pass @my_deco2 def func2(*func_args,**func_kwargs): pass @decorator def my_deco3(func,func_args,func_kwargs,x=1): pass @my_deco3() def func3(*func_args,**func_kwargs): pass """ arg_names, flags, defaults, deco_name = inspect_callable(deco) if flags & FUNC_ARGS == 0: if len(arg_names) < 3: raise TypeError('decorator functions need at least 3 ' + 'arguments (func, func_args, func_kwargs)') del arg_names[0:3] if not arg_names and flags & (FUNC_ARGS | FUNC_KWARGS) == 0: # argument-less decorator del arg_names, flags, defaults, deco_name @wraps(deco) def _deco(func): apply_func_args = args_applyer(*inspect_callable(func)) @wraps(func) def _f(*args,**kwargs): return deco(func,*apply_func_args(*args,**kwargs)) return _f return _deco else: apply_deco_args = args_applyer(arg_names,flags,defaults,deco_name) del arg_names, flags, defaults, deco_name @wraps(deco) def _deco_deco(*deco_args,**deco_kwargs): deco_args, deco_kwargs = apply_deco_args(*deco_args, **deco_kwargs) def _deco(func): apply_func_args = args_applyer(*inspect_callable(func)) @wraps(func) def _f(*func_args,**func_kwargs): func_args, func_kwargs = apply_func_args( *func_args, **func_kwargs) return deco(func,func_args,func_kwargs, *deco_args,**deco_kwargs) return _f return _deco return _deco_deco