No, importing a decorated function will not remove the decorator.
Importing retrieves the current object from the global namespace of the source module, and decorating a function causes the decorator return value to be stored in the global namespace.
Importing a module is mostly syntactic sugar for modulename = sys.modules['modulename']
(for import modulename
) and objectname = sys.modules['modulename'].objectname
assignments (for from modulename import objectname
, in either case after first ensuring that sys.modules
has the desired module loaded), and globals in a module are the same thing as attributes on a module object. Decorating is just syntactic sugar for functionname = decorator(functionobject)
.
If you need to add a new decorator to the imported function, just call the decorator:
from somemodule import somedecoratedfunction
newname_or_originalname = decorator(somedecoratedfunction)
If the imported decorated function doesn't lend itself to being decorated again in a new layer, or you want access to the original undecorated function, see if the object has a __wrapped__
attribute:
from somemodule import somedecoratedfunction
unwrapped_function = somedecoratedfunction.__wrapped__
A well-written decorators uses the @functools.wraps()
decorator, which sets that attribute to point to the original:
>>> from functools import wraps
>>> def demodecorator(f):
... @wraps(f)
... def wrapper(*args, **kwargs):
... print("Decorated!")
... return f(*args, **kwargs)
... return wrapper
...
>>> @demodecorator
... def foo(name):
... print(f"Hello, {name or 'World'}!")
...
>>> foo('cardamom')
Decorated!
Hello, cardamom!
>>> foo.__wrapped__('cardamom')
Hello, cardamom!