How can one attach a decorator to a function “after the fact” in python?

You imported sqrt into your module, just apply the decorator there in your own global namespace:

sqrt = print_args_decor(sqrt)

This sets the name sqrt in your module namespace to the result of the decorator. There is no requirement that sqrt was originally defined in this module.

It is up to the decorator to uses the functools.wraps() decorator to preserve function metadata such as the name and docstring.

Decorating a class is no different in this respect:

ClassName = decorator(ClassName)

On Python 2, for methods you need to be careful to grab the original unbound function; easiest is to use the method.__func__ attribute:

try:
    # Python 2
    ClassName.function_name = decorator(ClassName.function_name.__func__)
except AttributeError:
    # Python 3
    ClassName.function_name = decorator(ClassName.function_name)

I’ve wrapped the above in a try...except to make the pattern work across Python versions. The alternative is to grab the function object out of the class __dict__ to avoid the descriptor protocol from kicking in:

ClassName.function_name = decorator(ClassName.__dict__['function_name'])

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)