You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: decorator.py
+11-11
Original file line number
Diff line number
Diff line change
@@ -58,14 +58,14 @@ def __call__(self, x, y):
58
58
print_md("""
59
59
Function decorators take a given function, and intercept the call to that function. They act as a kind of proxy for calls of a given function.
60
60
This gives them the chance to add the following behavior:
61
-
- add code that is run before calling the intercepted function, it can also possibly alter the arguments of the function call
62
-
- add code that is run after calling the intercepted function, it can also alter the return value of the original function, before it is returned to the caller.
61
+
- add code that is run before calling the intercepted function, it can also alter the arguments of the function call, before they are passed to the intercepted/original function.
62
+
- add code that is run after calling the intercepted function, it can also alter the return value of the original function, before it is returned to the caller.
63
63
64
64
A function decorator therefore acts as a kind of 'smart proxy' around a given python function.
65
65
66
66
Lets start with an interceptor class, the class receives the wrapped function as an argument to its __init__ method;
67
67
The class is a callable object, and it calls the original function in its __call__ method.
68
-
The style of doing it as a class has a big plus: you can add instance variables to the decorator, like for example a counter calls to the original function.
68
+
The style of doing it as a class has a big plus: you can add instance variables to the decorator, like for example a counter of calls to the original function.
69
69
70
70
Here is the decorator class, that intercepts the calls to an argument function:
71
71
""")
@@ -78,15 +78,15 @@ class CountCalls:
78
78
def __init__(self, func):
79
79
80
80
# copy the __name__, ___qualname_, __doc__, __module__, __module__, __annotations__ attributes of the function argument into CountCalls instance,
81
-
# the CountCalls instance also gets a __wrapped__ attribute, which points to the wrapped function supplied by the func constructor argument.
81
+
# the CountCalls instance also gets a __wrapped__ attribute, which points to the intercepted/wrapped function supplied by the func constructor argument.
82
82
# as well as all entries in __dict__ of the wrapped function are copied into __dict__ member of the CountCalls instance.
83
83
# this is in order ot make the wrapper look the same as the wrapped function.
84
84
functools.update_wrapper(self, func)
85
85
86
-
# the forwarded function is copied, so that __call__ will be able to forward the call.
86
+
# the forwarded function put into an instance membe, so that __call__ will be able to forward the call.
87
87
self.func = func
88
88
89
-
# set the state variable, the number of calls, that is update upon each call.
89
+
# set the state variable, the number of calls. This counter is update upon each call.
90
90
self.num_calls = 0
91
91
92
92
# the __call__ function is called, when an instance of the CounCalls class is used as a function.
# return the value of the original function call is returned to the caller
108
+
# the return value of the original function call is returned to the caller
109
109
return ret_val
110
110
""")
111
111
@@ -118,7 +118,7 @@ def say_miau():
118
118
''' docstring: print the vocalization of a Felis Catus, also known as cat '''
119
119
print("Miau!")
120
120
121
-
# the global variable say_miau now refers to an object, that wraps the original say_miau function.
121
+
# the global variable say_miau now refers to an object, that wraps the original say_miau function.
122
122
say_miau = CountCalls(say_miau)
123
123
124
124
# the call to say_miau first calls the __call__ method of the CountCalls object,
@@ -148,7 +148,7 @@ def say_miau():
148
148
print_md("""
149
149
Attention!
150
150
Here is the equivalent way of setting up the decorator instance! just as the previous case, only for the say_woof method.
151
-
the @CountCalls syntax is supposed to be a shorter way of doing it the same assignment, as in the previous example!
151
+
the @CountCalls syntax is supposed to be a shorter way of doing the same assignment, as in the previous example!
152
152
""")
153
153
154
154
eval_and_quote("""
@@ -182,8 +182,8 @@ def inc_me(number_argument):
182
182
183
183
print_md("""
184
184
Lets look at the LimitCalls decorator, it can be used in different scenarios, it receives the following arguments
185
-
- log_calls - a boolean, it logs the call if set.
186
-
- max_calls - the maximum number of calls, if decorator does not forward the call to the original function, when the limit on the number of calls has been reached.
185
+
- log_calls - a boolean, it logs the call if set.
186
+
- max_calls - the maximum number of calls, if decorator does not forward the call to the original function, when the limit on the number of calls has been reached.
187
187
188
188
The class _LimitCalls starts with an underscore, to show that this is a private class, that is not supposed to be exported from a module.
0 commit comments