{"id":977,"date":"2020-11-06T09:47:02","date_gmt":"2020-11-06T09:47:02","guid":{"rendered":"https:\/\/www.pythontutorial.net\/?page_id=977"},"modified":"2025-03-27T13:50:42","modified_gmt":"2025-03-27T13:50:42","slug":"python-decorators","status":"publish","type":"page","link":"https:\/\/www.pythontutorial.net\/advanced-python\/python-decorators\/","title":{"rendered":"Python Decorators"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn about Python decorators and how to develop your own decorators.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='what-is-a-decorator-in-python'>What is a decorator in Python <a href=\"#what-is-a-decorator-in-python\" class=\"anchor\" id=\"what-is-a-decorator-in-python\" title=\"Anchor for What is a decorator in Python\">#<\/a><\/h2>\n\n\n\n<p>A decorator is a <a href=\"https:\/\/www.pythontutorial.net\/python-basics\/python-functions\/\">function<\/a> that takes another function as an argument and extends its behavior without changing the original function explicitly.<\/p>\n\n\n\n<p>Let&#8217;s take a simple example to understand the concept.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='a-simple-python-decorator-example'>A simple Python decorator example <a href=\"#a-simple-python-decorator-example\" class=\"anchor\" id=\"a-simple-python-decorator-example\" title=\"Anchor for A simple Python decorator example\">#<\/a><\/h2>\n\n\n\n<p>The following defines a <code>net_price<\/code> function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">net_price<\/span><span class=\"hljs-params\">(price, tax)<\/span>:<\/span>\n    <span class=\"hljs-string\">\"\"\" calculate the net price from price and tax\n    Arguments:\n        price: the selling price\n        tax: value added tax or sale tax\n    Return\n        the net price\n    \"\"\"<\/span>\n    <span class=\"hljs-keyword\">return<\/span> price * (<span class=\"hljs-number\">1<\/span> + tax)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>net_price<\/code> function calculates the net price from selling price and tax. It returns the <code>net_price<\/code> as a number.<\/p>\n\n\n\n<p>Suppose that you need to format the net price using the USD currency. For example, <code>100<\/code> becomes <code>$100<\/code>. To do it, you can use a decorator.<\/p>\n\n\n\n<p>By definition, a decorator is a function that takes a function as an argument:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">currency<\/span><span class=\"hljs-params\">(fn)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">pass<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>And it returns another function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">currency<\/span><span class=\"hljs-params\">(fn)<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">wrapper<\/span><span class=\"hljs-params\">(*args, **kwargs)<\/span>:<\/span>\n        fn(*args, **kwargs)\n\n    <span class=\"hljs-keyword\">return<\/span> wrapper<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>currency<\/code> function returns the <code>wrapper<\/code> function. The <code>wrapper<\/code> function has the <code>*args<\/code> and <code>**kwargs<\/code> parameters.<\/p>\n\n\n\n<p>These parameters allow you to call any <code>fn<\/code> function with any combination of positional and <a href=\"https:\/\/www.pythontutorial.net\/python-basics\/python-kwargs\/\">keyword-only arguments<\/a>.<\/p>\n\n\n\n<p>In this example, the <code>wrapper<\/code> function essentially executes the <code>fn<\/code> function directly and doesn&#8217;t change any behavior of the <code>fn<\/code> function.<\/p>\n\n\n\n<p>In the <code>wrapper<\/code> function, you can call the <code>fn<\/code> function, get its result, and format the result as a currency string:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">currency<\/span><span class=\"hljs-params\">(fn)<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">wrapper<\/span><span class=\"hljs-params\">(*args, **kwargs)<\/span>:<\/span>\n        result = fn(*args, **kwargs)\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f'$<span class=\"hljs-subst\">{result}<\/span>'<\/span>\n    <span class=\"hljs-keyword\">return<\/span> wrapper<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>currency<\/code> function is a decorator. <\/p>\n\n\n\n<p>It accepts any function that returns a number and formats that number as a currency string.<\/p>\n\n\n\n<p>To use the <code>currency<\/code> decorator, you need to pass the <code>net_price<\/code> function to it to get a new function and execute the new function as if it were the original function. For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">currency<\/span><span class=\"hljs-params\">(fn)<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">wrapper<\/span><span class=\"hljs-params\">(*args, **kwargs)<\/span>:<\/span>\n        result = fn(*args, **kwargs)\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f'$<span class=\"hljs-subst\">{result}<\/span>'<\/span>\n    <span class=\"hljs-keyword\">return<\/span> wrapper\n\nnet_price = currency(net_price)\nprint(net_price(<span class=\"hljs-number\">100<\/span>, <span class=\"hljs-number\">0.05<\/span>))<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><a href=\"https:\/\/www.pythontutorial.net\/playground\/?q=ZGVmIGN1cnJlbmN5KGZuKToKICAgIGRlZiB3cmFwcGVyKCphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgcmVzdWx0ID0gZm4oKmFyZ3MsICoqa3dhcmdzKQogICAgICAgIHJldHVybiBmJyR7cmVzdWx0fScKICAgIHJldHVybiB3cmFwcGVyCgpuZXRfcHJpY2UgPSBjdXJyZW5jeShuZXRfcHJpY2UpCnByaW50KG5ldF9wcmljZSgxMDAsIDAuMDUpKQ%3D%3D\" target=\"_blank\" rel=\"noreferrer noopener\">Try it<\/a><\/p>\n\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">$105.0<\/code><\/span><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='python-decorator-definition'>Python decorator definition <a href=\"#python-decorator-definition\" class=\"anchor\" id=\"python-decorator-definition\" title=\"Anchor for Python decorator definition\">#<\/a><\/h2>\n\n\n\n<p>In general, a decorator is:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A function that takes another function (original function) as an argument and returns another function (or <a href=\"https:\/\/www.pythontutorial.net\/advanced-python\/python-closures\/\">closure<\/a>)<\/li>\n\n\n\n<li>The closure typically accepts any combination of positional and keyword-only arguments.<\/li>\n\n\n\n<li>The closure function calls the original function using the arguments passed to the closure and returns the result of the function.<\/li>\n<\/ul>\n\n\n\n<p>The inner function is a closure because it references the <code>fn<\/code> argument from its enclosing scope or the decorator function.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='the-symbol'>The @ symbol <a href=\"#the-symbol\" class=\"anchor\" id=\"the-symbol\" title=\"Anchor for The @ symbol\">#<\/a><\/h2>\n\n\n\n<p>In the previous example, the currency is a decorator. And you can decorate the <code>net_price<\/code> function using the following syntax:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">net_price = currency(net_price)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Generally, if <code>decorate<\/code> is a decorator function and you want to decorate another function <code>fn<\/code>, you can use this syntax:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">fn = decorate(fn)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To make it more convenient, Python provides a shorter way like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">@decorate<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">fn<\/span><span class=\"hljs-params\">()<\/span>:<\/span>\n    <span class=\"hljs-keyword\">pass<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>For example, instead of using the following syntax:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">net_price = currency(net_price)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>&#8230; you can decorate the <code>net_price<\/code> function using the <code>@currency<\/code> as follows:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">@currency<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">net_price<\/span><span class=\"hljs-params\">(price, tax)<\/span>:<\/span>\n    <span class=\"hljs-string\">\"\"\" calculate the net price from price and tax\n    Arguments:\n        price: the selling price\n        tax: value added tax or sale tax\n    Return\n        the net price\n    \"\"\"<\/span>\n    <span class=\"hljs-keyword\">return<\/span> price * (<span class=\"hljs-number\">1<\/span> + tax)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Put it all together.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">currency<\/span><span class=\"hljs-params\">(fn)<\/span>:<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">wrapper<\/span><span class=\"hljs-params\">(*args, **kwargs)<\/span>:<\/span>\n        result = fn(*args, **kwargs)\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f'$<span class=\"hljs-subst\">{result}<\/span>'<\/span>\n    <span class=\"hljs-keyword\">return<\/span> wrapper\n\n\n<span class=\"hljs-meta\">@currency<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">net_price<\/span><span class=\"hljs-params\">(price, tax)<\/span>:<\/span>\n    <span class=\"hljs-string\">\"\"\" calculate the net price from price and tax\n    Arguments:\n        price: the selling price\n        tax: value added tax or sale tax\n    Return\n        the net price\n    \"\"\"<\/span>\n    <span class=\"hljs-keyword\">return<\/span> price * (<span class=\"hljs-number\">1<\/span> + tax)\n\n\nprint(net_price(<span class=\"hljs-number\">100<\/span>, <span class=\"hljs-number\">0.05<\/span>))<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><a href=\"https:\/\/www.pythontutorial.net\/playground\/?q=ZGVmIGN1cnJlbmN5KGZuKToKICAgIGRlZiB3cmFwcGVyKCphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgcmVzdWx0ID0gZm4oKmFyZ3MsICoqa3dhcmdzKQogICAgICAgIHJldHVybiBmJyR7cmVzdWx0fScKICAgIHJldHVybiB3cmFwcGVyCgoKQGN1cnJlbmN5CmRlZiBuZXRfcHJpY2UocHJpY2UsIHRheCk6CiAgICAiIiIgY2FsY3VsYXRlIHRoZSBuZXQgcHJpY2UgZnJvbSBwcmljZSBhbmQgdGF4CiAgICBBcmd1bWVudHM6CiAgICAgICAgcHJpY2U6IHRoZSBzZWxsaW5nIHByaWNlCiAgICAgICAgdGF4OiB2YWx1ZSBhZGRlZCB0YXggb3Igc2FsZSB0YXgKICAgIFJldHVybgogICAgICAgIHRoZSBuZXQgcHJpY2UKICAgICIiIgogICAgcmV0dXJuIHByaWNlICogKDEgKyB0YXgpCgoKcHJpbnQobmV0X3ByaWNlKDEwMCwgMC4wNSkp\" target=\"_blank\" rel=\"noreferrer noopener\">Try it<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='introspecting-decorated-functions'>Introspecting decorated functions <a href=\"#introspecting-decorated-functions\" class=\"anchor\" id=\"introspecting-decorated-functions\" title=\"Anchor for Introspecting decorated functions\">#<\/a><\/h2>\n\n\n\n<p>When you decorate a function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-meta\">@decorate<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">fn<\/span><span class=\"hljs-params\">(*args,**kwargs)<\/span>:<\/span>\n    <span class=\"hljs-keyword\">pass<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>It&#8217;s equivalent:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">fn = decorate(fn)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>decorate<\/code> function returns a new function, which is the wrapper function.<\/p>\n\n\n\n<p>If you use the built-in <code>help<\/code> function to show the documentation of the new function, you won&#8217;t see the documentation of the original function. For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">help(net_price)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">wrapper(*args, **kwargs)\n\nNone<\/code><\/span><\/pre>\n\n\n<p>Also, if you check the name of the new function, Python will return the name of the inner function returned by the decorator:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\">print(net_price.__name__)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">wrapper<\/code><\/span><\/pre>\n\n\n<p>So when you decorate a function, you&#8217;ll lose the original function signature and documentation.<\/p>\n\n\n\n<p>To fix this, you can use the <code>wraps<\/code> function from the <code>functools<\/code> standard module. In fact, the <code>wraps<\/code> function is also a decorator.<\/p>\n\n\n\n<p>The following shows how to use the <code>wraps<\/code> decorator:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python\"><span class=\"hljs-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> wraps\n\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">currency<\/span><span class=\"hljs-params\">(fn)<\/span>:<\/span>\n<span class=\"hljs-meta\">    @wraps(fn)<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">wrapper<\/span><span class=\"hljs-params\">(*args, **kwargs)<\/span>:<\/span>\n        result = fn(*args, **kwargs)\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">f'$<span class=\"hljs-subst\">{result}<\/span>'<\/span>\n    <span class=\"hljs-keyword\">return<\/span> wrapper\n\n\n<span class=\"hljs-meta\">@currency<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">net_price<\/span><span class=\"hljs-params\">(price, tax)<\/span>:<\/span>\n    <span class=\"hljs-string\">\"\"\" calculate the net price from price and tax\n    Arguments:\n        price: the selling price\n        tax: value added tax or sale tax\n    Return\n        the net price\n    \"\"\"<\/span>\n    <span class=\"hljs-keyword\">return<\/span> price * (<span class=\"hljs-number\">1<\/span> + tax)\n\n\nhelp(net_price)\nprint(net_price.__name__)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><a href=\"https:\/\/www.pythontutorial.net\/playground\/?q=ZnJvbSBmdW5jdG9vbHMgaW1wb3J0IHdyYXBzCgoKZGVmIGN1cnJlbmN5KGZuKToKICAgIEB3cmFwcyhmbikKICAgIGRlZiB3cmFwcGVyKCphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgcmVzdWx0ID0gZm4oKmFyZ3MsICoqa3dhcmdzKQogICAgICAgIHJldHVybiBmJyR7cmVzdWx0fScKICAgIHJldHVybiB3cmFwcGVyCgoKQGN1cnJlbmN5CmRlZiBuZXRfcHJpY2UocHJpY2UsIHRheCk6CiAgICAiIiIgY2FsY3VsYXRlIHRoZSBuZXQgcHJpY2UgZnJvbSBwcmljZSBhbmQgdGF4CiAgICBBcmd1bWVudHM6CiAgICAgICAgcHJpY2U6IHRoZSBzZWxsaW5nIHByaWNlCiAgICAgICAgdGF4OiB2YWx1ZSBhZGRlZCB0YXggb3Igc2FsZSB0YXgKICAgIFJldHVybgogICAgICAgIHRoZSBuZXQgcHJpY2UKICAgICIiIgogICAgcmV0dXJuIHByaWNlICogKDEgKyB0YXgpCgoKaGVscChuZXRfcHJpY2UpCnByaW50KG5ldF9wcmljZS5fX25hbWVfXyk%3D\" target=\"_blank\" rel=\"noreferrer noopener\">Try it<\/a><\/p>\n\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">net_price(price, tax)\n    calculate the net price <span class=\"hljs-keyword\">from<\/span> price and tax\n    <span class=\"hljs-attr\">Arguments<\/span>:\n        price: the selling price\n        <span class=\"hljs-attr\">tax<\/span>: value added tax or sale tax\n    Return\n        the net price\n\nnet_price    <\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='summary'>Summary <a href=\"#summary\" class=\"anchor\" id=\"summary\" title=\"Anchor for Summary\">#<\/a><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A decorator is a function that changes the behavior of another function without explicitly modifying it.<\/li>\n\n\n\n<li>Use the <code>@<\/code> symbol to decorate a function.<\/li>\n\n\n\n<li>Use the <code>wraps<\/code> function from the <code>functools<\/code> built-in module to retain the documentation and name of the original function.<\/li>\n<\/ul>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<header>\n\t\t<div class=\"wth-question\">Was this tutorial helpful ?<\/div>\n\t\t<div class=\"wth-thumbs\">\n\t\t\t<button\n\t\t\t\tdata-post=\"977\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/advanced-python\/python-decorators\/\"\n\t\t\t\tdata-post-title=\"Python Decorators\"\n\t\t\t\tdata-response=\"1\"\n\t\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t\t<\/button>\n\n\t\t\t<button\n\t\t\t\tdata-response=\"0\"\n\t\t\t\tdata-post=\"977\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/advanced-python\/python-decorators\/\"\n\t\t\t\tdata-post-title=\"Python Decorators\"\n\t\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t\t<\/button>\n\t\t<\/div>\n\t<\/header>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\t\t\t<input type=\"button\" name=\"wth-submit\" class=\"wth-btn wth-btn-submit\" id=\"wth-submit\" \/>\n\t\t\t<input type=\"button\" class=\"wth-btn wth-btn-cancel\" value=\"Cancel\" \/>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you&#8217;ll learn about Python decorators and how to develop your own decorators.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":757,"menu_order":9,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-977","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/977","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/comments?post=977"}],"version-history":[{"count":1,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/977\/revisions"}],"predecessor-version":[{"id":7111,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/977\/revisions\/7111"}],"up":[{"embeddable":true,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/757"}],"wp:attachment":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/media?parent=977"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}