|
| https://realpython.com/ |
| Start Here | https://realpython.com/start-here/ |
|
Learn Python
| https://realpython.com/lessons/debugging-code-decorators/ |
| Python Tutorials →In-depth articles and video courses | https://realpython.com/search?kind=article&kind=course&order=newest |
| Learning Paths →Guided study plans for accelerated learning | https://realpython.com/learning-paths/ |
| Quizzes & Exercises →Check your learning progress | https://realpython.com/quizzes/ |
| Browse Topics →Focus on a specific area or skill level | https://realpython.com/tutorials/all/ |
| Community Chat →Learn with other Pythonistas | https://realpython.com/community/ |
| Office Hours →Live Q&A calls with Python experts | https://realpython.com/office-hours/ |
| Podcast →Hear what’s new in the world of Python | https://realpython.com/podcasts/rpp/ |
| Books →Round out your knowledge and learn offline | https://realpython.com/products/books/ |
| Reference →Concise definitions for common Python terms | https://realpython.com/ref/ |
| Code Mentor →BetaPersonalized code assistance & learning tools | https://realpython.com/mentor/ |
| Unlock All Content → | https://realpython.com/account/join/ |
|
More
| https://realpython.com/lessons/debugging-code-decorators/ |
| Learner Stories | https://realpython.com/learner-stories/ |
| Python Newsletter | https://realpython.com/newsletter/ |
| Python Job Board | https://www.pythonjobshq.com |
| Meet the Team | https://realpython.com/team/ |
| Become a Contributor | https://realpython.com/jobs/ |
| Search | https://realpython.com/search |
| https://realpython.com/search |
| Join | https://realpython.com/account/join/ |
| Sign‑In | https://realpython.com/account/login/?next=%2Flessons%2Fdebugging-code-decorators%2F |
| Unlock This Lesson | https://realpython.com/account/join/?utm_source=rp_lesson&utm_content=python-decorators-101 |
| Unlock This Lesson | https://realpython.com/account/join/?utm_source=rp_lesson&utm_content=python-decorators-101 |
| https://realpython.com/courses/python-decorators-101/#team |
| Python Decorators 101 | https://realpython.com/courses/python-decorators-101/ |
| Christopher Bailey | https://realpython.com/courses/python-decorators-101/#team |
| Recommended Tutorial | https://realpython.com/primer-on-python-decorators/ |
| Course Slides (PDF) | https://realpython.com/courses/python-decorators-101/downloads/python-decorators-course-slides/ |
| Python Decorators Q&A Transcript (PDF) | https://realpython.com/courses/python-decorators-101/downloads/decorators-course-qa/ |
| Ask a Question | https://realpython.com/lessons/debugging-code-decorators/#discussion |
| https://realpython.com/feedback/survey/course/python-decorators-101/liked/?from=lesson-title |
| https://realpython.com/feedback/survey/course/python-decorators-101/disliked/?from=lesson-title |
| Contents | https://realpython.com/lessons/debugging-code-decorators/#description |
| Transcript | https://realpython.com/lessons/debugging-code-decorators/#transcript |
| Discussion (13) | https://realpython.com/lessons/debugging-code-decorators/#discussion |
| 00:00 | https://realpython.com/lessons/debugging-code-decorators/#t=0.72 |
| Now that you’ve timed some functions, how about debugging them? | https://realpython.com/lessons/debugging-code-decorators/#t=0.72 |
| This decorator’s going to name all the arguments that are passed in and out of | https://realpython.com/lessons/debugging-code-decorators/#t=5.22 |
| your function. So, this is our last decorator, @timer. | https://realpython.com/lessons/debugging-code-decorators/#t=9.18 |
| 00:14 | https://realpython.com/lessons/debugging-code-decorators/#t=14.52 |
| Just above it, if you have the boilerplate there, go ahead and copy it. | https://realpython.com/lessons/debugging-code-decorators/#t=14.52 |
| Then below timer(), paste that decorator. | https://realpython.com/lessons/debugging-code-decorators/#t=20.85 |
| I’ll leave some extra space. Okay. | https://realpython.com/lessons/debugging-code-decorators/#t=26.85 |
| 00:31 | https://realpython.com/lessons/debugging-code-decorators/#t=31.08 |
| The decorator is going to be named debug(). It’ll take a function, | https://realpython.com/lessons/debugging-code-decorators/#t=31.08 |
| create a docstring that says | https://realpython.com/lessons/debugging-code-decorators/#t=37.77 |
| 00:43 | https://realpython.com/lessons/debugging-code-decorators/#t=43.26 |
| """Print the function signature and return value""". | https://realpython.com/lessons/debugging-code-decorators/#t=43.26 |
| You’re still decorating your wrapper function with the @functools.wraps(). | https://realpython.com/lessons/debugging-code-decorators/#t=47.55 |
| 00:52 | https://realpython.com/lessons/debugging-code-decorators/#t=52.47 |
| The wrapper function for the decorator is going to be renamed wrapper_debug(). | https://realpython.com/lessons/debugging-code-decorators/#t=52.47 |
| 01:04 | https://realpython.com/lessons/debugging-code-decorators/#t=64.41 |
| You’ll assign args_repr. | https://realpython.com/lessons/debugging-code-decorators/#t=64.41 |
| So, this returns the canonical string representation of the object for a in args, | https://realpython.com/lessons/debugging-code-decorators/#t=67.74 |
| so this comprehension is going to return all the arguments out of args, | https://realpython.com/lessons/debugging-code-decorators/#t=72.84 |
| and this is going to create strings for each one. | https://realpython.com/lessons/debugging-code-decorators/#t=78.72 |
| 01:22 | https://realpython.com/lessons/debugging-code-decorators/#t=82.44 |
| You’ll do something very similar with the keyword arguments. | https://realpython.com/lessons/debugging-code-decorators/#t=82.44 |
| Using an f-string. | https://realpython.com/lessons/debugging-code-decorators/#t=87.96 |
| 01:39 | https://realpython.com/lessons/debugging-code-decorators/#t=99.81 |
| So here—don’t forget the s in .items()— | https://realpython.com/lessons/debugging-code-decorators/#t=99.81 |
| it’s going to create an iterable out of kwargs—that dictionary—and return each | https://realpython.com/lessons/debugging-code-decorators/#t=103.83 |
| key in value. Over here, | https://realpython.com/lessons/debugging-code-decorators/#t=107.97 |
| the f-string is going to format them, saying each key is equal to | https://realpython.com/lessons/debugging-code-decorators/#t=110.34 |
| the string representation of the value. | https://realpython.com/lessons/debugging-code-decorators/#t=116.1 |
| 02:01 | https://realpython.com/lessons/debugging-code-decorators/#t=121.92 |
| Next, you create a combined signature. | https://realpython.com/lessons/debugging-code-decorators/#t=121.92 |
| 02:11 | https://realpython.com/lessons/debugging-code-decorators/#t=131.22 |
| It’ll use this string method named .join() that will concatenate all of these | https://realpython.com/lessons/debugging-code-decorators/#t=131.22 |
| strings together. It will put this in between all of them. | https://realpython.com/lessons/debugging-code-decorators/#t=135.54 |
| So, what are you putting together? | https://realpython.com/lessons/debugging-code-decorators/#t=139.29 |
| 02:20 | https://realpython.com/lessons/debugging-code-decorators/#t=140.34 |
| args_repr and kwargs_repr. | https://realpython.com/lessons/debugging-code-decorators/#t=140.34 |
| 02:35 | https://realpython.com/lessons/debugging-code-decorators/#t=155.79 |
| Next, right before calling the function print(), using an f-string, | https://realpython.com/lessons/debugging-code-decorators/#t=155.79 |
| calling the function’s name using the .__name__ method, | https://realpython.com/lessons/debugging-code-decorators/#t=160.2 |
| and then this is a parentheses in between these two f-string expressions that | https://realpython.com/lessons/debugging-code-decorators/#t=163.53 |
| the signature then is going to be embedded in. So calling this function | https://realpython.com/lessons/debugging-code-decorators/#t=169.8 |
| using all of these arguments. Great. | https://realpython.com/lessons/debugging-code-decorators/#t=173.76 |
| 02:57 | https://realpython.com/lessons/debugging-code-decorators/#t=177.87 |
| Then, value will be set to the function with any *args and **kwargs coming in, | https://realpython.com/lessons/debugging-code-decorators/#t=177.87 |
| and what happens after? Print another f-string, | https://realpython.com/lessons/debugging-code-decorators/#t=184.96 |
| 03:11 | https://realpython.com/lessons/debugging-code-decorators/#t=191.17 |
| using .__name__ and the repr() version of it, saying how it returned the values | https://realpython.com/lessons/debugging-code-decorators/#t=191.17 |
| and the .__repr__ of all those—those repr() versions. | https://realpython.com/lessons/debugging-code-decorators/#t=198.4 |
| 03:22 | https://realpython.com/lessons/debugging-code-decorators/#t=202.99 |
| Next, you’re going return value, and last, you need to return the wrapper_debug. | https://realpython.com/lessons/debugging-code-decorators/#t=202.99 |
| Looks good! Now save. Okay. | https://realpython.com/lessons/debugging-code-decorators/#t=208.69 |
| Next up, open your examples module. | https://realpython.com/lessons/debugging-code-decorators/#t=213.34 |
| 03:39 | https://realpython.com/lessons/debugging-code-decorators/#t=219.79 |
| You are already importing from the decorators module | https://realpython.com/lessons/debugging-code-decorators/#t=219.79 |
| everything, by using this asterisk (*). Now, create a new function, | https://realpython.com/lessons/debugging-code-decorators/#t=224.44 |
| decorate it with @debug. | https://realpython.com/lessons/debugging-code-decorators/#t=229.42 |
| 03:54 | https://realpython.com/lessons/debugging-code-decorators/#t=234.28 |
| This function will be named make_greeting(). | https://realpython.com/lessons/debugging-code-decorators/#t=234.28 |
| It will take one positional argument, name, and one keyword argument, age, | https://realpython.com/lessons/debugging-code-decorators/#t=237.76 |
| which is set to None by default. Set up a conditional: | https://realpython.com/lessons/debugging-code-decorators/#t=243.82 |
| if age is None: return this f-string | https://realpython.com/lessons/debugging-code-decorators/#t=247.96 |
| with the expression name. else: return | https://realpython.com/lessons/debugging-code-decorators/#t=252.25 |
| with an f-string, using both of these arguments, both age and name. | https://realpython.com/lessons/debugging-code-decorators/#t=258.1 |
| 04:23 | https://realpython.com/lessons/debugging-code-decorators/#t=263.26 |
| Okay. So, make_greeting() requires a name as an argument, | https://realpython.com/lessons/debugging-code-decorators/#t=263.26 |
| and then also can take an age. | https://realpython.com/lessons/debugging-code-decorators/#t=266.92 |
| Then, it will print either of these two strings based upon the conditional | https://realpython.com/lessons/debugging-code-decorators/#t=269.11 |
| if statement there. Go ahead and save. | https://realpython.com/lessons/debugging-code-decorators/#t=274.51 |
| 04:40 | https://realpython.com/lessons/debugging-code-decorators/#t=280.39 |
| Now to use make_greeting(), you need to start your REPL, | https://realpython.com/lessons/debugging-code-decorators/#t=280.39 |
| and from your examples module, | https://realpython.com/lessons/debugging-code-decorators/#t=287.23 |
| import make_greeting. Great. It worked perfect. | https://realpython.com/lessons/debugging-code-decorators/#t=290.26 |
| 04:54 | https://realpython.com/lessons/debugging-code-decorators/#t=294.91 |
| Does it exist? Yep! There it is. | https://realpython.com/lessons/debugging-code-decorators/#t=294.91 |
| Let’s try it out and see how debugging works. First time, | https://realpython.com/lessons/debugging-code-decorators/#t=300.16 |
| say hello to "Benjamin". So here, | https://realpython.com/lessons/debugging-code-decorators/#t=304.06 |
| the @debug decorator said that it’s calling the function | https://realpython.com/lessons/debugging-code-decorators/#t=309.31 |
| make_greeting() with this argument, 'Benjamin'. | https://realpython.com/lessons/debugging-code-decorators/#t=312.7 |
| 05:15 | https://realpython.com/lessons/debugging-code-decorators/#t=315.53 |
| 'make_greeting'—the function name—returned 'Howdy Benjamin!' | https://realpython.com/lessons/debugging-code-decorators/#t=315.53 |
| And at the end here, there’s the string that was returned. | https://realpython.com/lessons/debugging-code-decorators/#t=320.0 |
| It looks like the @debug decorator’s working well. | https://realpython.com/lessons/debugging-code-decorators/#t=323.95 |
| 05:29 | https://realpython.com/lessons/debugging-code-decorators/#t=329.08 |
| How about if you said hello to "Richard"? | https://realpython.com/lessons/debugging-code-decorators/#t=329.08 |
| Set an age of 112. | https://realpython.com/lessons/debugging-code-decorators/#t=334.12 |
| 05:39 | https://realpython.com/lessons/debugging-code-decorators/#t=339.01 |
| So this time, it shows calling the function with 'Richard' as our positional | https://realpython.com/lessons/debugging-code-decorators/#t=339.01 |
| argument and the age key-value argument. | https://realpython.com/lessons/debugging-code-decorators/#t=343.12 |
| 'make_greeting' returned 'Whoa Richard! 112 already, you are growing up!' | https://realpython.com/lessons/debugging-code-decorators/#t=347.12 |
| And here, you see the f-string below. | https://realpython.com/lessons/debugging-code-decorators/#t=350.99 |
| 05:52 | https://realpython.com/lessons/debugging-code-decorators/#t=352.93 |
| This example might not seem immediately useful, since @debug the decorator is | https://realpython.com/lessons/debugging-code-decorators/#t=352.93 |
| just repeating what you wrote, | https://realpython.com/lessons/debugging-code-decorators/#t=357.83 |
| but I suggest you use it on a few more complex functions. And there’s another | https://realpython.com/lessons/debugging-code-decorators/#t=359.42 |
| advanced way to use it. | https://realpython.com/lessons/debugging-code-decorators/#t=363.59 |
| 06:05 | https://realpython.com/lessons/debugging-code-decorators/#t=365.45 |
| It’s actually more powerful when you apply it to a small convenience function | https://realpython.com/lessons/debugging-code-decorators/#t=365.45 |
| that you didn’t directly call yourself. Let me show you that as an example. | https://realpython.com/lessons/debugging-code-decorators/#t=368.48 |
| 06:14 | https://realpython.com/lessons/debugging-code-decorators/#t=374.3 |
| It’s going to calculate an approximation of the mathematical constant e. | https://realpython.com/lessons/debugging-code-decorators/#t=374.3 |
| So, you need to go back into your examples.py module, | https://realpython.com/lessons/debugging-code-decorators/#t=380.21 |
| and I need to import something else to do it. Not only import the decorators, | https://realpython.com/lessons/debugging-code-decorators/#t=386.99 |
| but import also—from the standard library—import math. | https://realpython.com/lessons/debugging-code-decorators/#t=391.7 |
| 06:38 | https://realpython.com/lessons/debugging-code-decorators/#t=398.59 |
| Now down here… | https://realpython.com/lessons/debugging-code-decorators/#t=398.59 |
| 06:46 | https://realpython.com/lessons/debugging-code-decorators/#t=406.1 |
| we’re going to reassign math.factorial to be a decorated version of it. | https://realpython.com/lessons/debugging-code-decorators/#t=406.1 |
| Notice that @debug is available, and debug() is going to call math.factorial. | https://realpython.com/lessons/debugging-code-decorators/#t=410.69 |
| 06:57 | https://realpython.com/lessons/debugging-code-decorators/#t=417.5 |
| This is kind of going back a little bit in time when we weren’t using the pretty | https://realpython.com/lessons/debugging-code-decorators/#t=417.5 |
| syntactic sugar of the @ symbol. | https://realpython.com/lessons/debugging-code-decorators/#t=421.55 |
| This is how we were using decorators before. You’d take a function and pass it as | https://realpython.com/lessons/debugging-code-decorators/#t=424.58 |
| an argument to your decorator. | https://realpython.com/lessons/debugging-code-decorators/#t=430.94 |
| 07:14 | https://realpython.com/lessons/debugging-code-decorators/#t=434.99 |
| Now, you’re going to approximate e. | https://realpython.com/lessons/debugging-code-decorators/#t=434.99 |
| By default, that’ll have a number of terms of 18. | https://realpython.com/lessons/debugging-code-decorators/#t=440.36 |
| 07:27 | https://realpython.com/lessons/debugging-code-decorators/#t=447.98 |
| So this is going to return the sum() of 1 divided by the factorial of n, for n | https://realpython.com/lessons/debugging-code-decorators/#t=447.98 |
| in the range() of the terms that you’ve entered as an argument. That factorial() | https://realpython.com/lessons/debugging-code-decorators/#t=455.81 |
| function will be called multiple times, depending on the range(). | https://realpython.com/lessons/debugging-code-decorators/#t=459.74 |
| 07:43 | https://realpython.com/lessons/debugging-code-decorators/#t=463.7 |
| If you’re interested in learning a little more about the math that’s going on | https://realpython.com/lessons/debugging-code-decorators/#t=463.7 |
| behind here, | https://realpython.com/lessons/debugging-code-decorators/#t=467.12 |
| there’s a link to the Wikipedia article in the written version of the tutorial. | https://realpython.com/lessons/debugging-code-decorators/#t=468.29 |
| 07:53 | https://realpython.com/lessons/debugging-code-decorators/#t=473.03 |
| Okay. Let me save, go ahead and exit the REPL, | https://realpython.com/lessons/debugging-code-decorators/#t=473.03 |
| and restart it. | https://realpython.com/lessons/debugging-code-decorators/#t=478.43 |
| 08:02 | https://realpython.com/lessons/debugging-code-decorators/#t=482.81 |
| And then import approximate_e. | https://realpython.com/lessons/debugging-code-decorators/#t=482.81 |
| Great. That worked good. Let’s make sure it’s there. Looks good! | https://realpython.com/lessons/debugging-code-decorators/#t=487.64 |
| What happens when you run it? | https://realpython.com/lessons/debugging-code-decorators/#t=491.75 |
| You can set a different number of terms. Cool! | https://realpython.com/lessons/debugging-code-decorators/#t=495.05 |
| 08:19 | https://realpython.com/lessons/debugging-code-decorators/#t=499.64 |
| So each time that factorial() runs, you can see it calling it. | https://realpython.com/lessons/debugging-code-decorators/#t=499.64 |
| It’s calling factorial() of 0, factorial() of 1, 2, 3, 4. | https://realpython.com/lessons/debugging-code-decorators/#t=503.63 |
| 08:30 | https://realpython.com/lessons/debugging-code-decorators/#t=510.53 |
| And you can see the values being returned each time. With the example you just | https://realpython.com/lessons/debugging-code-decorators/#t=510.53 |
| ran, | https://realpython.com/lessons/debugging-code-decorators/#t=514.309 |
| you get a decent approximate value for the true value of e. Another useful tool | https://realpython.com/lessons/debugging-code-decorators/#t=515.03 |
| for debugging functions— | https://realpython.com/lessons/debugging-code-decorators/#t=521.12 |
| besides showing arguments coming in and out—could be slowing down code, | https://realpython.com/lessons/debugging-code-decorators/#t=522.26 |
| especially if you’re using web services. Let me show you that next. | https://realpython.com/lessons/debugging-code-decorators/#t=526.28 |
| March 28, 2019 | https://realpython.com/lessons/debugging-code-decorators/#comment-9f027604-d2b1-497e-ae37-bbac89e166f4 |
| March 28, 2019 | https://realpython.com/lessons/debugging-code-decorators/#comment-8d11ea87-9225-4b01-9a07-3b3ffbb79819 |
| March 28, 2019 | https://realpython.com/lessons/debugging-code-decorators/#comment-ee30aa89-ef94-4dbb-837c-b6cfa726fd0f |
| March 28, 2019 | https://realpython.com/lessons/debugging-code-decorators/#comment-3c55841c-1f19-4a97-b934-cedf4b6058b5 |
| June 18, 2019 | https://realpython.com/lessons/debugging-code-decorators/#comment-3b032f9e-f2af-489b-822a-2ac89f3fca75 |
| account settings | https://realpython.com/account/ |
| Dec. 24, 2019 | https://realpython.com/lessons/debugging-code-decorators/#comment-ecf495fc-d843-4799-bf0f-05d56be1ee45 |
| Dec. 27, 2019 | https://realpython.com/lessons/debugging-code-decorators/#comment-8b0e4b00-ca24-4b7a-a5ef-485a476eb805 |
| Jan. 28, 2021 | https://realpython.com/lessons/debugging-code-decorators/#comment-5242b338-1ce1-43c9-b47a-d5f1698a3405 |
| Jan. 28, 2021 | https://realpython.com/lessons/debugging-code-decorators/#comment-37a06f79-7805-4ea7-8203-67efc65925ce |
| Jan. 29, 2021 | https://realpython.com/lessons/debugging-code-decorators/#comment-7b26a014-b18a-45c2-aa5d-4980b4ae80b2 |
| !r modifier | https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals |
| Dec. 25, 2021 | https://realpython.com/lessons/debugging-code-decorators/#comment-e0e35042-c46c-4017-8df5-9968ecf26b64 |
| Jan. 11, 2022 | https://realpython.com/lessons/debugging-code-decorators/#comment-f5417336-5076-4b95-b7c7-0ba4c41f18e1 |
| Jan. 11, 2022 | https://realpython.com/lessons/debugging-code-decorators/#comment-f6a08a9b-efc1-4852-85b8-c2c71da96cd1 |
| pydantic-docs.helpmanual.io/usage/validators/ | https://pydantic-docs.helpmanual.io/usage/validators/ |
| Become a Member | https://realpython.com/account/join/ |
| https://realpython.com/videos/timing-functions-decorators/ |
| Overview | https://realpython.com/courses/python-decorators-101/ |
| https://realpython.com/lessons/slowing-down-code-decorators/ |
|
Decorators Course Introduction and Overview 00:47
| https://realpython.com/videos/decorators-course-introduction-and-overview/ |
|
An Example Function 02:45
| https://realpython.com/videos/example-function/ |
|
Functions as First-Class Objects in Python 03:08
| https://realpython.com/videos/functions-first-class-objects-python/ |
|
Inner Functions 02:37
| https://realpython.com/lessons/inner-functions/ |
|
Returning Functions From Functions 03:23
| https://realpython.com/lessons/returning-functions-functions/ |
|
Section 1 Review 00:56
| https://realpython.com/lessons/decorators-section-1-review/ |
|
Section 2 Overview 00:31
| https://realpython.com/videos/decorators-section-2-overview/ |
|
Simple Decorators 06:16
| https://realpython.com/videos/simple-decorators/ |
|
Syntactic Sugar 02:53
| https://realpython.com/lessons/syntactic-sugar/ |
|
Reusing Decorators 02:37
| https://realpython.com/lessons/reusing-decorators/ |
|
Decorating Functions With Arguments 06:10
| https://realpython.com/lessons/decorating-functions-arguments/ |
|
Returning Values From Decorated Functions 03:22
| https://realpython.com/lessons/returning-values-decorated-functions/ |
|
Who Are You, Really? 05:45
| https://realpython.com/lessons/who-are-you-really/ |
|
Section 2 Review 01:20
| https://realpython.com/lessons/decorators-section-3-review/ |
|
Section 3 Overview 02:09
| https://realpython.com/videos/decorators-section-3-overview/ |
|
Timing Functions With Decorators 05:47
| https://realpython.com/videos/timing-functions-decorators/ |
|
Debugging Code With Decorators 08:50
| https://realpython.com/lessons/debugging-code-decorators/ |
|
Slowing Down Code With Decorators 03:31
| https://realpython.com/lessons/slowing-down-code-decorators/ |
|
Registering Plugins With Decorators 03:38
| https://realpython.com/lessons/registering-plugins-decorators/ |
|
Python Decorators (Quiz) 10:30
| https://realpython.com/lessons/python-decorators-quiz/ |
|
Decorators 101 Recap and Review 01:14
| https://realpython.com/lessons/decorators-101-recap-and-review/ |
| Privacy Policy | https://realpython.com/privacy-policy/ |
Viewport: width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover