I'm learning to use python decorator.
def my_dcrtr(fun):
def new_fun():
return fun()
return new_fun
I realize the decorated function 'fun' acts like a black box inside the decorator. I can choose to use fun() or not at all inside new_fun. However, I don't know whether I can break into 'fun' and interact with fun's local scope inside the new_fun?
e.g. I'm trying to make a toy Remote Procedural Call (RPC) with python.
def return_locals_rpc_decorator(fun):
def decorated_fun(*args, **kw):
local_args = fun(*args, **kw)
# pickle the local_args and send it to server
# server unpickle and doing the RPC
# fetch back server results and unpickle to results
return rpc_results
return decorated_fun
@return_locals_rpc_decorator
def rpc_fun(a, b, c=3):
return locals() # This looks weird. how can I make this part of the decorator?
print(rpc_fun(2, 1, 6))
In this example, I try to get rpc_fun's argument list at runtime with the 'locals()' command. Then send it to server to execute. Instead of letting rpc_fun returns its locals(), is it possible to use the decorator to retrieve decorated function's argument space?
Nesting means placing or storing inside the other. Therefore, Nested Decorators means applying more than one decorator inside a function. Python allows us to implement more than one decorator to a function. It makes decorators useful for reusable building blocks as it accumulates the several effects together.
Decorators provide a simple syntax for calling higher-order functions. By definition, a decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it.
Python class decorator It is possible to use classes as decorators. For this, we need to implement the __call__ magic function. In the example, we use a class decorator to count the calls of a regular function. We call the update_wrapper function.
A decorator is a function that takes another function as input, extends its behavior, and returns a new function as output.
You can use function annotations for Python3:
def return_locals_rpc_decorator(fun):
def decorated_fun(*args, **kw):
local_args = fun(*args, **kw)
print(local_args)
fun_parameters = fun.__annotations__
final_parameters = {a:list(args)[int(b[-1])-1] for a, b in fun_parameters.items() if a != 'return'}
return final_parameters
return decorated_fun
@return_locals_rpc_decorator
def my_funct(a:"val1", b:"val2", c:"val3") -> int:
return a + b + c
print(my_funct(10, 20, 30))
Output:
60
{'a': 10, 'b': 20, 'c': 30}
In this way, you are using the wrapper function decorated_fun
to access the decorated function's parameters and further information specified by the annotation. I changed the parameter descriptions in the annotations so that each string value would end in a digit that could be used to index args
. However, if you do not want to change the parameter descriptions in the annotations, you can sort via ending character.
Edit: the code in the body of my_funct
is executed when called in the wrapper function (decorated_fun
), since the args
, declared in the scope of decorated_fun
is passed to and unpacked in local_args
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With