Revisiting something I wrote. I had a long (to my taste) list of functions to define, that all had the same signature. Motivated exclusively by laziness, I did not want to write their list of keyword arguments (with their type hints) every time. So, I did something like
def my_signature(original_function):
def _wrapper(
value1: float,
value2: str,
value3: int
) -> float: # The original really had 6 arguments and types with longer names.
return original_function(value1=value1, value2=value2, value3=value3)
return _wrapper
# And then all the decorated function definitions
@my_signature
def function1(**kwargs) -> float:
...
@my_signature
def function2(**kwargs) -> float:
...
# ... etc.
I read the documentation of the decorator
module and it looks like my_signature
is changing more features from the original_function
than the signature.
Previously, you needed to manually copy the function attributes
__name__
,__doc__
,__module__
, and__dict__
to the decorated function by hand.
Question: What would be, or how to find out, the complete list of attributes to copy over from original_function
to _wrapper
?
Question: If a place to look is dir(original_function)
, are there some of those that I should not copy from original_function
to _wrapper
?
For example, in the source code of the module decorator
, I see them copying the following, where there are entries from dir(func)
that are not being copied over. One example is __le__
, among others.
fun.__name__ = func.__name__
fun.__doc__ = func.__doc__
fun.__wrapped__ = func
fun.__signature__ = sig
fun.__qualname__ = func.__qualname__
# builtin functions like defaultdict.__setitem__ lack many attributes
try:
fun.__defaults__ = func.__defaults__
except AttributeError:
pass
try:
fun.__kwdefaults__ = func.__kwdefaults__
except AttributeError:
pass
try:
fun.__annotations__ = func.__annotations__
except AttributeError:
pass
try:
fun.__module__ = func.__module__
except AttributeError:
pass
try:
fun.__dict__.update(func.__dict__)
except AttributeError:
pass