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: concepts/decorators/about.md
+84-79Lines changed: 84 additions & 79 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -120,40 +120,41 @@ The inner function may then return the original function argument.
120
120
Following is an example of a decorator being used for validation:
121
121
122
122
```python
123
-
>>>defmy_validator(func):
124
-
...defmy_wrapper(world):
125
-
...print(f"Entering {func.__name__} with {world} argument")
126
-
...if ("Pluto"== world):
127
-
...print("Pluto is not a planet!")
128
-
...else:
129
-
...return func(world)
130
-
...return my_wrapper
131
-
...
132
-
...@my_validator
133
-
...defmy_func(planet):
134
-
...print(f"Hello, {planet}!")
135
-
...
136
-
>>> my_func("World")
137
-
Entering my_func with World argument
138
-
Hello, World!
139
-
...
140
-
>>> my_func("Pluto")
141
-
Entering my_func with Pluto argument
142
-
Pluto isnot a planet!
123
+
defmy_validator(func):
124
+
defmy_wrapper(world):
125
+
print(f"Entering {func.__name__} with {world} argument")
126
+
127
+
if world =="Pluto":
128
+
print("Pluto is not a planet!")
129
+
else:
130
+
return func(world)
131
+
return my_wrapper
132
+
133
+
@my_validator
134
+
defmy_func(planet):
135
+
print(f"Hello, {planet}!")
136
+
137
+
my_func("World")
138
+
#-> Entering my_func with World argument
139
+
#-> Hello, World!
140
+
141
+
my_func("Pluto")
142
+
#-> Entering my_func with Pluto argument
143
+
#-> Pluto is not a planet!
143
144
```
144
145
145
-
On the first line, we have the definition for the decorator with its`func` argument.
146
-
On the next line is the definition for the decorators_inner function_, which wraps the `func` argument.
146
+
On the first line, we have the definition for the decorator's`func` argument.
147
+
On the next line is the definition for the decorator's_inner function_, which wraps the `func` argument.
147
148
Since the _inner function_ wraps the decorator's `func` argument, it is passed the same argument that is passed to `func`.
148
149
Note that the wrapper doesn't have to use the same name for the argument that was defined in `func`.
149
-
The original function uses `planet` and the decorator uses `world`, and the decorator still works.
150
+
The original function uses `planet` and the decorator uses `world` — and the decorator still works.
150
151
151
-
The inner function returns either `func`or, if `planet` equals `Pluto`, it will print that Pluto is not a planet.
152
+
The inner function returns either `func`— or if `world == "Pluto"` — prints that Pluto is not a planet.
152
153
It could be coded to raise a `ValueError` instead.
153
-
So, the inner function wraps `func`, and returns either `func` or does something that substitutes what `func` would do.
154
+
So, the _inner function_ wraps `func`, and returns either `func` or does something that substitutes for what `func` would do.
154
155
The decorator returns its _inner function_.
155
-
The _inner_function_ may or may not return the original, passed-in function.
156
-
Depending on what code conditionally executes in the wrapper function or _inner_function_, `func` may be returned, an error could be raised, or a value of `func`'s return type could be returned.
156
+
The _inner function_ may or may not return the original, passed-in function.
157
+
Depending on what code conditionally executes in the wrapper function or _inner function_, `func` may be returned, an error could be raised, or a value of `func`'s return type could be returned.
157
158
158
159
### Decorating a Function that Takes an Arbitrary Number of Arguments
159
160
@@ -162,19 +163,20 @@ Decorators can be written for functions that take an arbitrary number of argumen
162
163
Following is an example of a decorator for a function that takes an arbitrary number of arguments:
163
164
164
165
```python
165
-
>>>defdouble(func):
166
-
...defwrapper(*args, **kwargs):
167
-
...return func(*args, **kwargs) *2
168
-
...return wrapper
169
-
...
170
-
...@double
171
-
...defadd(*args):
172
-
...returnsum(args)
173
-
...
174
-
>>>print(add(2, 3, 4))
175
-
18
176
-
>>>print(add(2, 3, 4, 5, 6))
177
-
40
166
+
defdouble(func):
167
+
defwrapper(*args, **kwargs):
168
+
return func(*args, **kwargs) *2
169
+
return wrapper
170
+
171
+
@double
172
+
defadd(*args):
173
+
returnsum(args)
174
+
175
+
print(add(2, 3, 4))
176
+
#-> 18
177
+
178
+
print(add(2, 3, 4, 5, 6))
179
+
#-> 40
178
180
```
179
181
180
182
This works for doubling the return value from the function argument.
@@ -185,24 +187,25 @@ If we want to triple, quadruple, etc. the return value, we can add a parameter t
185
187
Following is an example of a decorator that can be configured to multiply the decorated function's return value by an arbitrary amount:
186
188
187
189
```python
188
-
>>>defmulti(factor=1):
189
-
...if (factor ==0):
190
-
...raiseValueError("factor must not be 0")
191
-
...
192
-
...defouter_wrapper(func):
193
-
...definner_wrapper(*args, **kwargs):
194
-
...return func(*args, **kwargs) * factor
195
-
...return inner_wrapper
196
-
...return outer_wrapper
197
-
...
198
-
...@multi(factor=3)
199
-
...defadd(*args):
200
-
...returnsum(args)
201
-
...
202
-
>>>print(add(2, 3, 4))
203
-
27
204
-
>>>print(add(2, 3, 4, 5, 6))
205
-
60
190
+
defmulti(factor=1):
191
+
if factor ==0:
192
+
raiseValueError("factor must not be 0")
193
+
194
+
defouter_wrapper(func):
195
+
definner_wrapper(*args, **kwargs):
196
+
return func(*args, **kwargs) * factor
197
+
return inner_wrapper
198
+
return outer_wrapper
199
+
200
+
@multi(factor=3)
201
+
defadd(*args):
202
+
returnsum(args)
203
+
204
+
print(add(2, 3, 4))
205
+
#-> 27
206
+
207
+
print(add(2, 3, 4, 5, 6))
208
+
#-> 60
206
209
```
207
210
208
211
The first lines validate that `factor` is not `0`.
@@ -215,27 +218,29 @@ The outer wrapper returns the inner wrapper, and the decorator returns the outer
215
218
Following is an example of a parameterized decorator that controls whether it validates the argument passed to the original function:
216
219
217
220
```python
218
-
>>>defcheck_for_pluto(check=True):
219
-
...defmy_validator(func):
220
-
...defmy_wrapper(world):
221
-
...print(f"Entering {func.__name__} with {world} argument")
222
-
...if (check and"Pluto"== world):
223
-
...print("Pluto is not a planet!")
224
-
...else:
225
-
...return func(world)
226
-
...return my_wrapper
227
-
...return my_validator
228
-
...
229
-
...@check_for_pluto(check=False)
230
-
...defmy_func(planet):
231
-
...print(f"Hello, {planet}!")
232
-
...
233
-
>>> my_func("World")
234
-
Entering my_func with World argument
235
-
Hello, World!
236
-
>>> my_func("Pluto")
237
-
Entering my_func with Pluto argument
238
-
Hello, Pluto!
221
+
defcheck_for_pluto(check=True):
222
+
defmy_validator(func):
223
+
defmy_wrapper(world):
224
+
print(f"Entering {func.__name__} with {world} argument")
225
+
if check and world =="Pluto":
226
+
print("Pluto is not a planet!")
227
+
else:
228
+
return func(world)
229
+
230
+
return my_wrapper
231
+
return my_validator
232
+
233
+
@check_for_pluto(check=False)
234
+
defmy_func(planet):
235
+
print(f"Hello, {planet}!")
236
+
237
+
my_func("World")
238
+
#-> Entering my_func with World argument
239
+
#-> Hello, World!
240
+
241
+
my_func("Pluto")
242
+
#-> Entering my_func with Pluto argument
243
+
#-> Hello, Pluto!
239
244
```
240
245
241
246
This allows for easy toggling between checking for `Pluto` or not, and is done without having to modify `my_func`.
0 commit comments