{"id":1006,"date":"2020-11-10T01:21:32","date_gmt":"2020-11-10T01:21:32","guid":{"rendered":"https:\/\/www.pythontutorial.net\/?page_id=1006"},"modified":"2025-03-27T13:54:01","modified_gmt":"2025-03-27T13:54:01","slug":"python-decorator-arguments","status":"publish","type":"page","link":"https:\/\/www.pythontutorial.net\/advanced-python\/python-decorator-arguments\/","title":{"rendered":"Python Decorator with Arguments"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn how to define Python decorators with arguments using a decorator factory.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='introduction-to-python-decorator-with-arguments'>Introduction to Python decorator with arguments <a href=\"#introduction-to-python-decorator-with-arguments\" class=\"anchor\" id=\"introduction-to-python-decorator-with-arguments\" title=\"Anchor for Introduction to Python decorator with arguments\">#<\/a><\/h2>\n\n\n\n<p>Suppose that you have a <a href=\"https:\/\/www.pythontutorial.net\/python-basics\/python-functions\/\">function<\/a> called <code>say<\/code> that prints out a message:<\/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\">say<\/span><span class=\"hljs-params\">(message)<\/span>:<\/span>\n    <span class=\"hljs-string\">''' print the message \n    Arguments\n        message: the message to show\n    '''<\/span>\n    print(message)<\/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>and you want to execute the <code>say()<\/code> function 5 times repeatedly each time you call it. For example:<\/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\">say(<span class=\"hljs-string\">'Hi'<\/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>It should show the following the <code>Hi<\/code> message five times as follows:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">Hi\nHi\nHi\nHi\nHi<\/code><\/span><\/pre>\n\n\n<p>To do that, you can use a regular <a href=\"https:\/\/www.pythontutorial.net\/advanced-python\/python-decorators\/\">decorator<\/a>:<\/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-meta\">@repeat<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">say<\/span><span class=\"hljs-params\">(message)<\/span>:<\/span>\n    <span class=\"hljs-string\">''' print the message \n    Arguments\n        message: the message to show\n    '''<\/span>\n    print(message)\n<\/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>And you can define the <code>repeat<\/code> decorator as follows:<\/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\">repeat<\/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        <span class=\"hljs-keyword\">for<\/span> _ <span class=\"hljs-keyword\">in<\/span> range(<span class=\"hljs-number\">5<\/span>):\n            result = fn(*args, **kwargs)\n        <span class=\"hljs-keyword\">return<\/span> result\n\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 following shows the complete code:<\/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-keyword\">from<\/span> functools <span class=\"hljs-keyword\">import<\/span> wraps\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">repeat<\/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        <span class=\"hljs-keyword\">for<\/span> _ <span class=\"hljs-keyword\">in<\/span> range(<span class=\"hljs-number\">5<\/span>):\n            result = fn(*args, **kwargs)\n        <span class=\"hljs-keyword\">return<\/span> result\n\n    <span class=\"hljs-keyword\">return<\/span> wrapper\n\n\n<span class=\"hljs-meta\">@repeat<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">say<\/span><span class=\"hljs-params\">(message)<\/span>:<\/span>\n    <span class=\"hljs-string\">''' print the message \n    Arguments\n        message: the message to show\n    '''<\/span>\n    print(message)\n\n\nsay(<span class=\"hljs-string\">'Hello'<\/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=ZnJvbSBmdW5jdG9vbHMgaW1wb3J0IHdyYXBzCgpkZWYgcmVwZWF0KGZuKToKICAgIEB3cmFwcyhmbikKICAgIGRlZiB3cmFwcGVyKCphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgZm9yIF8gaW4gcmFuZ2UoNSk6CiAgICAgICAgICAgIHJlc3VsdCA9IGZuKCphcmdzLCAqKmt3YXJncykKICAgICAgICByZXR1cm4gcmVzdWx0CgogICAgcmV0dXJuIHdyYXBwZXIKCgpAcmVwZWF0CmRlZiBzYXkobWVzc2FnZSk6CiAgICAnJycgcHJpbnQgdGhlIG1lc3NhZ2UgCiAgICBBcmd1bWVudHMKICAgICAgICBtZXNzYWdlOiB0aGUgbWVzc2FnZSB0byBzaG93CiAgICAnJycKICAgIHByaW50KG1lc3NhZ2UpCgoKc2F5KCdIZWxsbycp\" target=\"_blank\" rel=\"noreferrer noopener\">Try it<\/a><\/p>\n\n\n\n<p>What if you want to execute the <code>say()<\/code> function repeatedly ten times. In this case, you need to change the hard-coded value 5 in the <code>repeat<\/code> decorator.<\/p>\n\n\n\n<p>However, this solution isn&#8217;t flexible. For example, you want to use the <code>repeat<\/code> decorator to execute a function 5 times and another 10 times. The <code>repeat<\/code> decorator would not meet the requirement.<\/p>\n\n\n\n<p>To fix this, you need to change the <code>repeat<\/code> decorator so that it accepts an argument that specifies the number of times a function should execute like this:<\/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\"><span class=\"hljs-meta\">@repeat(5)<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">say<\/span><span class=\"hljs-params\">(message)<\/span>:<\/span>\n    ...\n<\/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>To define the <code>repeat<\/code> decorator, the <code>repeat(5)<\/code> should return the original decorator.<\/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\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">repeat<\/span><span class=\"hljs-params\">(times)<\/span>:<\/span>\n    <span class=\"hljs-comment\"># return the original \"repeat\" decorator<\/span>\n<\/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>The new <code>repeat<\/code> function returns a decorator. And it&#8217;s often referred to as a decorator factory.<\/p>\n\n\n\n<p>The following <code>repeat<\/code> function returns a decorator:<\/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-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">repeat<\/span><span class=\"hljs-params\">(times)<\/span>:<\/span>\n    <span class=\"hljs-string\">''' call a function a number of times '''<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">decorate<\/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            <span class=\"hljs-keyword\">for<\/span> _ <span class=\"hljs-keyword\">in<\/span> range(times):\n                result = fn(*args, **kwargs)\n            <span class=\"hljs-keyword\">return<\/span> result\n        <span class=\"hljs-keyword\">return<\/span> wrapper\n    <span class=\"hljs-keyword\">return<\/span> decorate\n<\/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>In this code, the <code>decorate<\/code> function is a decorator. It&#8217;s equivalent to the original <code>repeat<\/code> decorator.<\/p>\n\n\n\n<p>Note that the new repeat function isn&#8217;t a decorator. It&#8217;s a decorator factory that returns a decorator.<\/p>\n\n\n\n<p>Put it all together.<\/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\"><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\">repeat<\/span><span class=\"hljs-params\">(times)<\/span>:<\/span>\n    <span class=\"hljs-string\">''' call a function a number of times '''<\/span>\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">decorate<\/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            <span class=\"hljs-keyword\">for<\/span> _ <span class=\"hljs-keyword\">in<\/span> range(times):\n                result = fn(*args, **kwargs)\n            <span class=\"hljs-keyword\">return<\/span> result\n        <span class=\"hljs-keyword\">return<\/span> wrapper\n    <span class=\"hljs-keyword\">return<\/span> decorate\n\n\n<span class=\"hljs-meta\">@repeat(10)<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">def<\/span> <span class=\"hljs-title\">say<\/span><span class=\"hljs-params\">(message)<\/span>:<\/span>\n    <span class=\"hljs-string\">''' print the message \n    Arguments\n        message: the message to show\n    '''<\/span>\n    print(message)\n\n\nsay(<span class=\"hljs-string\">'Hello'<\/span>)\n<\/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><a href=\"https:\/\/www.pythontutorial.net\/playground\/?q=ZnJvbSBmdW5jdG9vbHMgaW1wb3J0IHdyYXBzCgoKZGVmIHJlcGVhdCh0aW1lcyk6CiAgICAnJycgY2FsbCBhIGZ1bmN0aW9uIGEgbnVtYmVyIG9mIHRpbWVzICcnJwogICAgZGVmIGRlY29yYXRlKGZuKToKICAgICAgICBAd3JhcHMoZm4pCiAgICAgICAgZGVmIHdyYXBwZXIoKmFyZ3MsICoqa3dhcmdzKToKICAgICAgICAgICAgZm9yIF8gaW4gcmFuZ2UodGltZXMpOgogICAgICAgICAgICAgICAgcmVzdWx0ID0gZm4oKmFyZ3MsICoqa3dhcmdzKQogICAgICAgICAgICByZXR1cm4gcmVzdWx0CiAgICAgICAgcmV0dXJuIHdyYXBwZXIKICAgIHJldHVybiBkZWNvcmF0ZQoKCkByZXBlYXQoMTApCmRlZiBzYXkobWVzc2FnZSk6CiAgICAnJycgcHJpbnQgdGhlIG1lc3NhZ2UgCiAgICBBcmd1bWVudHMKICAgICAgICBtZXNzYWdlOiB0aGUgbWVzc2FnZSB0byBzaG93CiAgICAnJycKICAgIHByaW50KG1lc3NhZ2UpCgoKc2F5KCdIZWxsbycp\" 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-10\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">Hello\nHello\nHello\nHello\nHello\nHello\nHello\nHello\nHello\nHello<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/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>Use a factory decorator to return a decorator that accepts arguments.<\/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=\"1006\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/advanced-python\/python-decorator-arguments\/\"\n\t\t\t\tdata-post-title=\"Python Decorator with Arguments\"\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=\"1006\"\n\t\t\t\tdata-post-url=\"https:\/\/www.pythontutorial.net\/advanced-python\/python-decorator-arguments\/\"\n\t\t\t\tdata-post-title=\"Python Decorator with Arguments\"\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 how to define Python decorators with arguments by using a decorator factory.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":757,"menu_order":10,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1006","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/1006","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=1006"}],"version-history":[{"count":2,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/1006\/revisions"}],"predecessor-version":[{"id":7113,"href":"https:\/\/www.pythontutorial.net\/wp-json\/wp\/v2\/pages\/1006\/revisions\/7113"}],"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=1006"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}