'<!DOCTYPE html>\n<html lang="en" prefix="og: http://ogp.me/ns# fb: https://www.facebook.com/2008/fbml">\n<head>\n <title>Python Decorator - Jerrylsu.net</title>\n <!-- Using the latest rendering mode for IE -->\n <meta http-equiv="X-UA-Compatible" content="IE=edge">\n <meta charset="utf-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n\n\n <link href="/jerry.jpg" rel="icon">\n\n<link rel="canonical" href="/articles/2020/programming-Python-Decorator.html">\n\n <meta name="author" content="Jerry Su" />\n <meta name="keywords" content="Python" />\n <meta name="description" content="0. 装饰器¶装饰器:接收一个函数(被装饰的函数)对象,返回一个函数(已装饰的函数)对象。动态的给一个对象添加额外职责,即装饰器设计模式。 装饰器的典型行为:把被装饰的函数替换为新函数,二者接收的参数相同,并返回被装饰函数本该的返回值,同时增加一些额外操作。 func = factorial, factorial = clocked clock是装饰器 factorial是被装饰函数 clocked是被装饰后的函数 factorial作为func参数传递给装饰器clock,装饰器clock返回clocked函数并复制给factorial。func是clocked的自由变量,两者构成闭包。 当调用函数factorial时,实际上调用函数locked,而locked函数中func则为被装饰的函数factorial。" />\n\n <meta property="og:site_name" content="Jerrylsu.net" />\n <meta property="og:type" content="article"/>\n <meta property="og:title" content="Python Decorator"/>\n <meta property="og:url" content="/articles/2020/programming-Python-Decorator.html"/>\n <meta property="og:description" content="0. 装饰器¶装饰器:接收一个函数(被装饰的函数)对象,返回一个函数(已装饰的函数)对象。动态的给一个对象添加额外职责,即装饰器设计模式。 装饰器的典型行为:把被装饰的函数替换为新函数,二者接收的参数相同,并返回被装饰函数本该的返回值,同时增加一些额外操作。 func = factorial, factorial = clocked clock是装饰器 factorial是被装饰函数 clocked是被装饰后的函数 factorial作为func参数传递给装饰器clock,装饰器clock返回clocked函数并复制给factorial。func是clocked的自由变量,两者构成闭包。 当调用函数factorial时,实际上调用函数locked,而locked函数中func则为被装饰的函数factorial。"/>\n <meta property="article:published_time" content="2020-12-20" />\n <meta property="article:section" content="Programming" />\n <meta property="article:tag" content="Python" />\n <meta property="article:author" content="Jerry Su" />\n\n\n\n <!-- Bootstrap -->\n <link rel="stylesheet" href="/theme/css/bootstrap.min.css" type="text/css"/>\n <link href="/theme/css/font-awesome.min.css" rel="stylesheet">\n\n <link href="/theme/css/pygments/colorful.css" rel="stylesheet">\n <link href="/theme/tipuesearch/tipuesearch.css" rel="stylesheet">\n <link rel="stylesheet" href="/theme/css/style.css" type="text/css"/>\n\n\n\n</head>\n<body>\n\n<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">\n <div class="container-fluid">\n <div class="navbar-header">\n <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">\n <span class="sr-only">Toggle navigation</span>\n <span class="icon-bar"></span>\n <span class="icon-bar"></span>\n <span class="icon-bar"></span>\n </button>\n <a href="/" class="navbar-brand">\nJerrylsu.net </a>\n </div>\n <div class="collapse navbar-collapse navbar-ex1-collapse">\n <ul class="nav navbar-nav">\n <li><a href="/pages/about.html">\n ABOUT\n </a></li>\n <li><a href="/pages/algorithms.html">\n ALGORITHMS\n </a></li>\n <li><a href="/pages/books.html">\n BOOKS\n </a></li>\n <li><a href="/pages/projects.html">\n PROJECTS\n </a></li>\n <li><a href="/pages/python.html">\n PYTHON\n </a></li>\n <li><a href="/pages/tensorflow.html">\n TENSORFLOW\n </a></li>\n </ul>\n <ul class="nav navbar-nav navbar-right">\n <li><span>\n <form class="navbar-search" action="/search.html">\n <input type="text" class="search-query" placeholder="Search" name="q" id="tipue_search_input" required>\n </form></span>\n </li>\n <li><a href="/articles/index.html"><i class="fa fa-th-list"></i><span class="icon-label">Archives</span></a></li>\n </ul>\n </div>\n <!-- /.navbar-collapse -->\n </div>\n</div> <!-- /.navbar -->\n\n<!-- Banner -->\n<!-- End Banner -->\n\n<!-- Content Container -->\n<div class="container-fluid">\n <div class="row">\n <div class="col-sm-9 col-sm-push-3">\n <ol class="breadcrumb">\n <li><a href="" title="Jerrylsu.net"><i class="fa fa-home fa-lg"></i></a></li>\n <li><a href="/categories/programming.html" title="Programming">Programming</a></li>\n <li class="active">Python Decorator</li>\n </ol>\n <section id="content">\n <article>\n <header class="page-header">\n <h1>\n <a href="/articles/2020/programming-Python-Decorator.html"\n rel="bookmark"\n title="Permalink to Python Decorator">\n Python Decorator\n </a>\n </h1>\n </header>\n <div class="entry-content">\n <div class="panel">\n <div class="panel-body">\n<footer class="post-info">\n <span class="label label-default">Date</span>\n <span class="published">\n <i class="fa fa-calendar"></i><time datetime="2020-12-20T10:17:17+08:00"> 2020-12-20 Sun</time>\n </span>\n\n\n\n\n\n<span class="label label-default">Tags</span>\n\t<a href="/tags/python.html">Python</a>\n \n</footer><!-- /.post-info --> </div>\n </div>\n <style type="text/css">/*!\n*\n* IPython notebook\n*\n*/\n/* CSS font colors for translated ANSI escape sequences */\n/* The color values are a mix of\n http://www.xcolors.net/dl/baskerville-ivorylight and\n http://www.xcolors.net/dl/euphrasia */\n.ansi-black-fg {\n color: #3E424D;\n}\n.ansi-black-bg {\n background-color: #3E424D;\n}\n.ansi-black-intense-fg {\n color: #282C36;\n}\n.ansi-black-intense-bg {\n background-color: #282C36;\n}\n.ansi-red-fg {\n color: #E75C58;\n}\n.ansi-red-bg {\n background-color: #E75C58;\n}\n.ansi-red-intense-fg {\n color: #B22B31;\n}\n.ansi-red-intense-bg {\n background-color: #B22B31;\n}\n.ansi-green-fg {\n color: #00A250;\n}\n.ansi-green-bg {\n background-color: #00A250;\n}\n.ansi-green-intense-fg {\n color: #007427;\n}\n.ansi-green-intense-bg {\n background-color: #007427;\n}\n.ansi-yellow-fg {\n color: #DDB62B;\n}\n.ansi-yellow-bg {\n background-color: #DDB62B;\n}\n.ansi-yellow-intense-fg {\n color: #B27D12;\n}\n.ansi-yellow-intense-bg {\n background-color: #B27D12;\n}\n.ansi-blue-fg {\n color: #208FFB;\n}\n.ansi-blue-bg {\n background-color: #208FFB;\n}\n.ansi-blue-intense-fg {\n color: #0065CA;\n}\n.ansi-blue-intense-bg {\n background-color: #0065CA;\n}\n.ansi-magenta-fg {\n color: #D160C4;\n}\n.ansi-magenta-bg {\n background-color: #D160C4;\n}\n.ansi-magenta-intense-fg {\n color: #A03196;\n}\n.ansi-magenta-intense-bg {\n background-color: #A03196;\n}\n.ansi-cyan-fg {\n color: #60C6C8;\n}\n.ansi-cyan-bg {\n background-color: #60C6C8;\n}\n.ansi-cyan-intense-fg {\n color: #258F8F;\n}\n.ansi-cyan-intense-bg {\n background-color: #258F8F;\n}\n.ansi-white-fg {\n color: #C5C1B4;\n}\n.ansi-white-bg {\n background-color: #C5C1B4;\n}\n.ansi-white-intense-fg {\n color: #A1A6B2;\n}\n.ansi-white-intense-bg {\n background-color: #A1A6B2;\n}\n.ansi-default-inverse-fg {\n color: #FFFFFF;\n}\n.ansi-default-inverse-bg {\n background-color: #000000;\n}\n.ansi-bold {\n font-weight: bold;\n}\n.ansi-underline {\n text-decoration: underline;\n}\n/* The following styles are deprecated an will be removed in a future version */\n.ansibold {\n font-weight: bold;\n}\n.ansi-inverse {\n outline: 0.5px dotted;\n}\n/* use dark versions for foreground, to improve visibility */\n.ansiblack {\n color: black;\n}\n.ansired {\n color: darkred;\n}\n.ansigreen {\n color: darkgreen;\n}\n.ansiyellow {\n color: #c4a000;\n}\n.ansiblue {\n color: darkblue;\n}\n.ansipurple {\n color: darkviolet;\n}\n.ansicyan {\n color: steelblue;\n}\n.ansigray {\n color: gray;\n}\n/* and light for background, for the same reason */\n.ansibgblack {\n background-color: black;\n}\n.ansibgred {\n background-color: red;\n}\n.ansibggreen {\n background-color: green;\n}\n.ansibgyellow {\n background-color: yellow;\n}\n.ansibgblue {\n background-color: blue;\n}\n.ansibgpurple {\n background-color: magenta;\n}\n.ansibgcyan {\n background-color: cyan;\n}\n.ansibggray {\n background-color: gray;\n}\ndiv.cell {\n /* Old browsers */\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-box-align: stretch;\n display: -moz-box;\n -moz-box-orient: vertical;\n -moz-box-align: stretch;\n display: box;\n box-orient: vertical;\n box-align: stretch;\n /* Modern browsers */\n display: flex;\n flex-direction: column;\n align-items: stretch;\n border-radius: 2px;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n -webkit-box-sizing: border-box;\n border-width: 1px;\n border-style: solid;\n border-color: transparent;\n width: 100%;\n padding: 5px;\n /* This acts as a spacer between cells, that is outside the border */\n margin: 0px;\n outline: none;\n position: relative;\n overflow: visible;\n}\ndiv.cell:before {\n position: absolute;\n display: block;\n top: -1px;\n left: -1px;\n width: 5px;\n height: calc(100% + 2px);\n content: \'\';\n background: transparent;\n}\ndiv.cell.jupyter-soft-selected {\n border-left-color: #E3F2FD;\n border-left-width: 1px;\n padding-left: 5px;\n border-right-color: #E3F2FD;\n border-right-width: 1px;\n background: #E3F2FD;\n}\n@media print {\n div.cell.jupyter-soft-selected {\n border-color: transparent;\n }\n}\ndiv.cell.selected,\ndiv.cell.selected.jupyter-soft-selected {\n border-color: #ababab;\n}\ndiv.cell.selected:before,\ndiv.cell.selected.jupyter-soft-selected:before {\n position: absolute;\n display: block;\n top: -1px;\n left: -1px;\n width: 5px;\n height: calc(100% + 2px);\n content: \'\';\n background: #42A5F5;\n}\n@media print {\n div.cell.selected,\n div.cell.selected.jupyter-soft-selected {\n border-color: transparent;\n }\n}\n.edit_mode div.cell.selected {\n border-color: #66BB6A;\n}\n.edit_mode div.cell.selected:before {\n position: absolute;\n display: block;\n top: -1px;\n left: -1px;\n width: 5px;\n height: calc(100% + 2px);\n content: \'\';\n background: #66BB6A;\n}\n@media print {\n .edit_mode div.cell.selected {\n border-color: transparent;\n }\n}\n.prompt {\n /* This needs to be wide enough for 3 digit prompt numbers: In[100]: */\n min-width: 14ex;\n /* This padding is tuned to match the padding on the CodeMirror editor. */\n padding: 0.4em;\n margin: 0px;\n font-family: monospace;\n text-align: right;\n /* This has to match that of the the CodeMirror class line-height below */\n line-height: 1.21429em;\n /* Don\'t highlight prompt number selection */\n -webkit-touch-callout: none;\n -webkit-user-select: none;\n -khtml-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n /* Use default cursor */\n cursor: default;\n}\n@media (max-width: 540px) {\n .prompt {\n text-align: left;\n }\n}\ndiv.inner_cell {\n min-width: 0;\n /* Old browsers */\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-box-align: stretch;\n display: -moz-box;\n -moz-box-orient: vertical;\n -moz-box-align: stretch;\n display: box;\n box-orient: vertical;\n box-align: stretch;\n /* Modern browsers */\n display: flex;\n flex-direction: column;\n align-items: stretch;\n /* Old browsers */\n -webkit-box-flex: 1;\n -moz-box-flex: 1;\n box-flex: 1;\n /* Modern browsers */\n flex: 1;\n}\n/* input_area and input_prompt must match in top border and margin for alignment */\ndiv.input_area {\n border: 1px solid #cfcfcf;\n border-radius: 2px;\n background: #f7f7f7;\n line-height: 1.21429em;\n}\n/* This is needed so that empty prompt areas can collapse to zero height when there\n is no content in the output_subarea and the prompt. The main purpose of this is\n to make sure that empty JavaScript output_subareas have no height. */\ndiv.prompt:empty {\n padding-top: 0;\n padding-bottom: 0;\n}\ndiv.unrecognized_cell {\n padding: 5px 5px 5px 0px;\n /* Old browsers */\n display: -webkit-box;\n -webkit-box-orient: horizontal;\n -webkit-box-align: stretch;\n display: -moz-box;\n -moz-box-orient: horizontal;\n -moz-box-align: stretch;\n display: box;\n box-orient: horizontal;\n box-align: stretch;\n /* Modern browsers */\n display: flex;\n flex-direction: row;\n align-items: stretch;\n}\ndiv.unrecognized_cell .inner_cell {\n border-radius: 2px;\n padding: 5px;\n font-weight: bold;\n color: red;\n border: 1px solid #cfcfcf;\n background: #eaeaea;\n}\ndiv.unrecognized_cell .inner_cell a {\n color: inherit;\n text-decoration: none;\n}\ndiv.unrecognized_cell .inner_cell a:hover {\n color: inherit;\n text-decoration: none;\n}\n@media (max-width: 540px) {\n div.unrecognized_cell > div.prompt {\n display: none;\n }\n}\ndiv.code_cell {\n /* avoid page breaking on code cells when printing */\n}\n@media print {\n div.code_cell {\n page-break-inside: avoid;\n }\n}\n/* any special styling for code cells that are currently running goes here */\ndiv.input {\n page-break-inside: avoid;\n /* Old browsers */\n display: -webkit-box;\n -webkit-box-orient: horizontal;\n -webkit-box-align: stretch;\n display: -moz-box;\n -moz-box-orient: horizontal;\n -moz-box-align: stretch;\n display: box;\n box-orient: horizontal;\n box-align: stretch;\n /* Modern browsers */\n display: flex;\n flex-direction: row;\n align-items: stretch;\n}\n@media (max-width: 540px) {\n div.input {\n /* Old browsers */\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-box-align: stretch;\n display: -moz-box;\n -moz-box-orient: vertical;\n -moz-box-align: stretch;\n display: box;\n box-orient: vertical;\n box-align: stretch;\n /* Modern browsers */\n display: flex;\n flex-direction: column;\n align-items: stretch;\n }\n}\n/* input_area and input_prompt must match in top border and margin for alignment */\ndiv.input_prompt {\n color: #303F9F;\n border-top: 1px solid transparent;\n}\ndiv.input_area > div.highlight {\n margin: 0.4em;\n border: none;\n padding: 0px;\n background-color: transparent;\n}\ndiv.input_area > div.highlight > pre {\n margin: 0px;\n border: none;\n padding: 0px;\n background-color: transparent;\n}\n/* The following gets added to the <head> if it is detected that the user has a\n * monospace font with inconsistent normal/bold/italic height. See\n * notebookmain.js. Such fonts will have keywords vertically offset with\n * respect to the rest of the text. The user should select a better font.\n * See: https://github.com/ipython/ipython/issues/1503\n *\n * .CodeMirror span {\n * vertical-align: bottom;\n * }\n */\n.CodeMirror {\n line-height: 1.21429em;\n /* Changed from 1em to our global default */\n font-size: 14px;\n height: auto;\n /* Changed to auto to autogrow */\n background: none;\n /* Changed from white to allow our bg to show through */\n}\n.CodeMirror-scroll {\n /* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*/\n /* We have found that if it is visible, vertical scrollbars appear with font size changes.*/\n overflow-y: hidden;\n overflow-x: auto;\n}\n.CodeMirror-lines {\n /* In CM2, this used to be 0.4em, but in CM3 it went to 4px. We need the em value because */\n /* we have set a different line-height and want this to scale with that. */\n /* Note that this should set vertical padding only, since CodeMirror assumes\n that horizontal padding will be set on CodeMirror pre */\n padding: 0.4em 0;\n}\n.CodeMirror-linenumber {\n padding: 0 8px 0 4px;\n}\n.CodeMirror-gutters {\n border-bottom-left-radius: 2px;\n border-top-left-radius: 2px;\n}\n.CodeMirror pre {\n /* In CM3 this went to 4px from 0 in CM2. This sets horizontal padding only,\n use .CodeMirror-lines for vertical */\n padding: 0 0.4em;\n border: 0;\n border-radius: 0;\n}\n.CodeMirror-cursor {\n border-left: 1.4px solid black;\n}\n@media screen and (min-width: 2138px) and (max-width: 4319px) {\n .CodeMirror-cursor {\n border-left: 2px solid black;\n }\n}\n@media screen and (min-width: 4320px) {\n .CodeMirror-cursor {\n border-left: 4px solid black;\n }\n}\n/*\n\nOriginal style from softwaremaniacs.org (c) Ivan Sagalaev <Maniac@SoftwareManiacs.Org>\nAdapted from GitHub theme\n\n*/\n.highlight-base {\n color: #000;\n}\n.highlight-variable {\n color: #000;\n}\n.highlight-variable-2 {\n color: #1a1a1a;\n}\n.highlight-variable-3 {\n color: #333333;\n}\n.highlight-string {\n color: #BA2121;\n}\n.highlight-comment {\n color: #408080;\n font-style: italic;\n}\n.highlight-number {\n color: #080;\n}\n.highlight-atom {\n color: #88F;\n}\n.highlight-keyword {\n color: #008000;\n font-weight: bold;\n}\n.highlight-builtin {\n color: #008000;\n}\n.highlight-error {\n color: #f00;\n}\n.highlight-operator {\n color: #AA22FF;\n font-weight: bold;\n}\n.highlight-meta {\n color: #AA22FF;\n}\n/* previously not defined, copying from default codemirror */\n.highlight-def {\n color: #00f;\n}\n.highlight-string-2 {\n color: #f50;\n}\n.highlight-qualifier {\n color: #555;\n}\n.highlight-bracket {\n color: #997;\n}\n.highlight-tag {\n color: #170;\n}\n.highlight-attribute {\n color: #00c;\n}\n.highlight-header {\n color: blue;\n}\n.highlight-quote {\n color: #090;\n}\n.highlight-link {\n color: #00c;\n}\n/* apply the same style to codemirror */\n.cm-s-ipython span.cm-keyword {\n color: #008000;\n font-weight: bold;\n}\n.cm-s-ipython span.cm-atom {\n color: #88F;\n}\n.cm-s-ipython span.cm-number {\n color: #080;\n}\n.cm-s-ipython span.cm-def {\n color: #00f;\n}\n.cm-s-ipython span.cm-variable {\n color: #000;\n}\n.cm-s-ipython span.cm-operator {\n color: #AA22FF;\n font-weight: bold;\n}\n.cm-s-ipython span.cm-variable-2 {\n color: #1a1a1a;\n}\n.cm-s-ipython span.cm-variable-3 {\n color: #333333;\n}\n.cm-s-ipython span.cm-comment {\n color: #408080;\n font-style: italic;\n}\n.cm-s-ipython span.cm-string {\n color: #BA2121;\n}\n.cm-s-ipython span.cm-string-2 {\n color: #f50;\n}\n.cm-s-ipython span.cm-meta {\n color: #AA22FF;\n}\n.cm-s-ipython span.cm-qualifier {\n color: #555;\n}\n.cm-s-ipython span.cm-builtin {\n color: #008000;\n}\n.cm-s-ipython span.cm-bracket {\n color: #997;\n}\n.cm-s-ipython span.cm-tag {\n color: #170;\n}\n.cm-s-ipython span.cm-attribute {\n color: #00c;\n}\n.cm-s-ipython span.cm-header {\n color: blue;\n}\n.cm-s-ipython span.cm-quote {\n color: #090;\n}\n.cm-s-ipython span.cm-link {\n color: #00c;\n}\n.cm-s-ipython span.cm-error {\n color: #f00;\n}\n.cm-s-ipython span.cm-tab {\n background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);\n background-position: right;\n background-repeat: no-repeat;\n}\ndiv.output_wrapper {\n /* this position must be relative to enable descendents to be absolute within it */\n position: relative;\n /* Old browsers */\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-box-align: stretch;\n display: -moz-box;\n -moz-box-orient: vertical;\n -moz-box-align: stretch;\n display: box;\n box-orient: vertical;\n box-align: stretch;\n /* Modern browsers */\n display: flex;\n flex-direction: column;\n align-items: stretch;\n z-index: 1;\n}\n/* class for the output area when it should be height-limited */\ndiv.output_scroll {\n /* ideally, this would be max-height, but FF barfs all over that */\n height: 24em;\n /* FF needs this *and the wrapper* to specify full width, or it will shrinkwrap */\n width: 100%;\n overflow: auto;\n border-radius: 2px;\n -webkit-box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.8);\n box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.8);\n display: block;\n}\n/* output div while it is collapsed */\ndiv.output_collapsed {\n margin: 0px;\n padding: 0px;\n /* Old browsers */\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-box-align: stretch;\n display: -moz-box;\n -moz-box-orient: vertical;\n -moz-box-align: stretch;\n display: box;\n box-orient: vertical;\n box-align: stretch;\n /* Modern browsers */\n display: flex;\n flex-direction: column;\n align-items: stretch;\n}\ndiv.out_prompt_overlay {\n height: 100%;\n padding: 0px 0.4em;\n position: absolute;\n border-radius: 2px;\n}\ndiv.out_prompt_overlay:hover {\n /* use inner shadow to get border that is computed the same on WebKit/FF */\n -webkit-box-shadow: inset 0 0 1px #000;\n box-shadow: inset 0 0 1px #000;\n background: rgba(240, 240, 240, 0.5);\n}\ndiv.output_prompt {\n color: #D84315;\n}\n/* This class is the outer container of all output sections. */\ndiv.output_area {\n padding: 0px;\n page-break-inside: avoid;\n /* Old browsers */\n display: -webkit-box;\n -webkit-box-orient: horizontal;\n -webkit-box-align: stretch;\n display: -moz-box;\n -moz-box-orient: horizontal;\n -moz-box-align: stretch;\n display: box;\n box-orient: horizontal;\n box-align: stretch;\n /* Modern browsers */\n display: flex;\n flex-direction: row;\n align-items: stretch;\n}\ndiv.output_area .MathJax_Display {\n text-align: left !important;\n}\ndiv.output_area \ndiv.output_area \ndiv.output_area img,\ndiv.output_area svg {\n max-width: 100%;\n height: auto;\n}\ndiv.output_area img.unconfined,\ndiv.output_area svg.unconfined {\n max-width: none;\n}\ndiv.output_area .mglyph > img {\n max-width: none;\n}\n/* This is needed to protect the pre formating from global settings such\n as that of bootstrap */\n.output {\n /* Old browsers */\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-box-align: stretch;\n display: -moz-box;\n -moz-box-orient: vertical;\n -moz-box-align: stretch;\n display: box;\n box-orient: vertical;\n box-align: stretch;\n /* Modern browsers */\n display: flex;\n flex-direction: column;\n align-items: stretch;\n}\n@media (max-width: 540px) {\n div.output_area {\n /* Old browsers */\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-box-align: stretch;\n display: -moz-box;\n -moz-box-orient: vertical;\n -moz-box-align: stretch;\n display: box;\n box-orient: vertical;\n box-align: stretch;\n /* Modern browsers */\n display: flex;\n flex-direction: column;\n align-items: stretch;\n }\n}\ndiv.output_area pre {\n margin: 0;\n padding: 1px 0 1px 0;\n border: 0;\n vertical-align: baseline;\n color: black;\n background-color: transparent;\n border-radius: 0;\n}\n/* This class is for the output subarea inside the output_area and after\n the prompt div. */\ndiv.output_subarea {\n overflow-x: auto;\n padding: 0.4em;\n /* Old browsers */\n -webkit-box-flex: 1;\n -moz-box-flex: 1;\n box-flex: 1;\n /* Modern browsers */\n flex: 1;\n max-width: calc(100% - 14ex);\n}\ndiv.output_scroll div.output_subarea {\n overflow-x: visible;\n}\n/* The rest of the output_* classes are for special styling of the different\n output types */\n/* all text output has this class: */\ndiv.output_text {\n text-align: left;\n color: #000;\n /* This has to match that of the the CodeMirror class line-height below */\n line-height: 1.21429em;\n}\n/* stdout/stderr are \'text\' as well as \'stream\', but execute_result/error are *not* streams */\ndiv.output_stderr {\n background: #fdd;\n /* very light red background for stderr */\n}\ndiv.output_latex {\n text-align: left;\n}\n/* Empty output_javascript divs should have no height */\ndiv.output_javascript:empty {\n padding: 0;\n}\n.js-error {\n color: darkred;\n}\n/* raw_input styles */\ndiv.raw_input_container {\n line-height: 1.21429em;\n padding-top: 5px;\n}\npre.raw_input_prompt {\n /* nothing needed here. */\n}\ninput.raw_input {\n font-family: monospace;\n font-size: inherit;\n color: inherit;\n width: auto;\n /* make sure input baseline aligns with prompt */\n vertical-align: baseline;\n /* padding + margin = 0.5em between prompt and cursor */\n padding: 0em 0.25em;\n margin: 0em 0.25em;\n}\ninput.raw_input:focus {\n box-shadow: none;\n}\np.p-space {\n margin-bottom: 10px;\n}\ndiv.output_unrecognized {\n padding: 5px;\n font-weight: bold;\n color: red;\n}\ndiv.output_unrecognized a {\n color: inherit;\n text-decoration: none;\n}\ndiv.output_unrecognized a:hover {\n color: inherit;\n text-decoration: none;\n}\n.rendered_html {\n color: #000;\n /* any extras will just be numbers: */\n}\n\n\n\n.rendered_html :link {\n text-decoration: underline;\n}\n.rendered_html :visited {\n text-decoration: underline;\n}\n\n\n\n\n\n\n.rendered_html h1:first-child {\n margin-top: 0.538em;\n}\n.rendered_html h2:first-child {\n margin-top: 0.636em;\n}\n.rendered_html h3:first-child {\n margin-top: 0.777em;\n}\n.rendered_html h4:first-child {\n margin-top: 1em;\n}\n.rendered_html h5:first-child {\n margin-top: 1em;\n}\n.rendered_html h6:first-child {\n margin-top: 1em;\n}\n.rendered_html ul:not(.list-inline),\n.rendered_html ol:not(.list-inline) {\n padding-left: 2em;\n}\n\n\n\n\n\n\n\n\n.rendered_html * + ul {\n margin-top: 1em;\n}\n.rendered_html * + ol {\n margin-top: 1em;\n}\n\n\n\n\n\n.rendered_html pre,\n\n\n\n\n.rendered_html tr,\n.rendered_html th,\n\n\n.rendered_html tbody tr:nth-child(odd) {\n background: #f5f5f5;\n}\n.rendered_html tbody tr:hover {\n background: rgba(66, 165, 245, 0.2);\n}\n.rendered_html * + table {\n margin-top: 1em;\n}\n\n.rendered_html * + p {\n margin-top: 1em;\n}\n\n.rendered_html * + img {\n margin-top: 1em;\n}\n.rendered_html img,\n\n.rendered_html img.unconfined,\n\n\n.rendered_html * + .alert {\n margin-top: 1em;\n}\n[dir="rtl"] \ndiv.text_cell {\n /* Old browsers */\n display: -webkit-box;\n -webkit-box-orient: horizontal;\n -webkit-box-align: stretch;\n display: -moz-box;\n -moz-box-orient: horizontal;\n -moz-box-align: stretch;\n display: box;\n box-orient: horizontal;\n box-align: stretch;\n /* Modern browsers */\n display: flex;\n flex-direction: row;\n align-items: stretch;\n}\n@media (max-width: 540px) {\n div.text_cell > div.prompt {\n display: none;\n }\n}\ndiv.text_cell_render {\n /*font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;*/\n outline: none;\n resize: none;\n width: inherit;\n border-style: none;\n padding: 0.5em 0.5em 0.5em 0.4em;\n color: #000;\n box-sizing: border-box;\n -moz-box-sizing: border-box;\n -webkit-box-sizing: border-box;\n}\na.anchor-link:link {\n text-decoration: none;\n padding: 0px 20px;\n visibility: hidden;\n}\nh1:hover .anchor-link,\nh2:hover .anchor-link,\nh3:hover .anchor-link,\nh4:hover .anchor-link,\nh5:hover .anchor-link,\nh6:hover .anchor-link {\n visibility: visible;\n}\n.text_cell.rendered .input_area {\n display: none;\n}\n.text_cell.rendered \n.text_cell.rendered .rendered_html tr,\n.text_cell.rendered .rendered_html th,\n.text_cell.rendered \n.text_cell.unrendered .text_cell_render {\n display: none;\n}\n.text_cell .dropzone .input_area {\n border: 2px dashed #bababa;\n margin: -1px;\n}\n.cm-header-1,\n.cm-header-2,\n.cm-header-3,\n.cm-header-4,\n.cm-header-5,\n.cm-header-6 {\n font-weight: bold;\n font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;\n}\n.cm-header-1 {\n font-size: 185.7%;\n}\n.cm-header-2 {\n font-size: 157.1%;\n}\n.cm-header-3 {\n font-size: 128.6%;\n}\n.cm-header-4 {\n font-size: 110%;\n}\n.cm-header-5 {\n font-size: 100%;\n font-style: italic;\n}\n.cm-header-6 {\n font-size: 100%;\n font-style: italic;\n}\n</style>\n<style type="text/css"> .highlight pre .hll { background-color: #ffffcc }\n .highlight pre { background: #f8f8f8; }\n .highlight pre .c { color: #408080; font-style: italic } /* Comment */\n .highlight pre .err { border: 1px solid #FF0000 } /* Error */\n .highlight pre .k { color: #008000; font-weight: bold } /* Keyword */\n .highlight pre .o { color: #666666 } /* Operator */\n .highlight pre .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n .highlight pre .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n .highlight pre .cp { color: #BC7A00 } /* Comment.Preproc */\n .highlight pre .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n .highlight pre .c1 { color: #408080; font-style: italic } /* Comment.Single */\n .highlight pre .cs { color: #408080; font-style: italic } /* Comment.Special */\n .highlight pre .gd { color: #A00000 } /* Generic.Deleted */\n .highlight pre .ge { font-style: italic } /* Generic.Emph */\n .highlight pre .gr { color: #FF0000 } /* Generic.Error */\n .highlight pre .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n .highlight pre .gi { color: #00A000 } /* Generic.Inserted */\n .highlight pre .go { color: #888888 } /* Generic.Output */\n .highlight pre .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n .highlight pre .gs { font-weight: bold } /* Generic.Strong */\n .highlight pre .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n .highlight pre .gt { color: #0044DD } /* Generic.Traceback */\n .highlight pre .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n .highlight pre .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n .highlight pre .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n .highlight pre .kp { color: #008000 } /* Keyword.Pseudo */\n .highlight pre .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n .highlight pre .kt { color: #B00040 } /* Keyword.Type */\n .highlight pre .m { color: #666666 } /* Literal.Number */\n .highlight pre .s { color: #BA2121 } /* Literal.String */\n .highlight pre .na { color: #7D9029 } /* Name.Attribute */\n .highlight pre .nb { color: #008000 } /* Name.Builtin */\n .highlight pre .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n .highlight pre .no { color: #880000 } /* Name.Constant */\n .highlight pre .nd { color: #AA22FF } /* Name.Decorator */\n .highlight pre .ni { color: #999999; font-weight: bold } /* Name.Entity */\n .highlight pre .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n .highlight pre .nf { color: #0000FF } /* Name.Function */\n .highlight pre .nl { color: #A0A000 } /* Name.Label */\n .highlight pre .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n .highlight pre .nt { color: #008000; font-weight: bold } /* Name.Tag */\n .highlight pre .nv { color: #19177C } /* Name.Variable */\n .highlight pre .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n .highlight pre .w { color: #bbbbbb } /* Text.Whitespace */\n .highlight pre .mb { color: #666666 } /* Literal.Number.Bin */\n .highlight pre .mf { color: #666666 } /* Literal.Number.Float */\n .highlight pre .mh { color: #666666 } /* Literal.Number.Hex */\n .highlight pre .mi { color: #666666 } /* Literal.Number.Integer */\n .highlight pre .mo { color: #666666 } /* Literal.Number.Oct */\n .highlight pre .sa { color: #BA2121 } /* Literal.String.Affix */\n .highlight pre .sb { color: #BA2121 } /* Literal.String.Backtick */\n .highlight pre .sc { color: #BA2121 } /* Literal.String.Char */\n .highlight pre .dl { color: #BA2121 } /* Literal.String.Delimiter */\n .highlight pre .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n .highlight pre .s2 { color: #BA2121 } /* Literal.String.Double */\n .highlight pre .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n .highlight pre .sh { color: #BA2121 } /* Literal.String.Heredoc */\n .highlight pre .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n .highlight pre .sx { color: #008000 } /* Literal.String.Other */\n .highlight pre .sr { color: #BB6688 } /* Literal.String.Regex */\n .highlight pre .s1 { color: #BA2121 } /* Literal.String.Single */\n .highlight pre .ss { color: #19177C } /* Literal.String.Symbol */\n .highlight pre .bp { color: #008000 } /* Name.Builtin.Pseudo */\n .highlight pre .fm { color: #0000FF } /* Name.Function.Magic */\n .highlight pre .vc { color: #19177C } /* Name.Variable.Class */\n .highlight pre .vg { color: #19177C } /* Name.Variable.Global */\n .highlight pre .vi { color: #19177C } /* Name.Variable.Instance */\n .highlight pre .vm { color: #19177C } /* Name.Variable.Magic */\n .highlight pre .il { color: #666666 } /* Literal.Number.Integer.Long */</style><body><div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">\n</div><div class="inner_cell">\n<div class="text_cell_render border-box-sizing rendered_html">\n<h2 id="0.-装饰器">0. 装饰器<a class="anchor-link" href="#0.-装饰器">¶</a></h2><p>装饰器:接收一个函数(被装饰的函数)对象,返回一个函数(已装饰的函数)对象。动态的给一个对象添加额外职责,即装饰器设计模式。</p>\n<p>装饰器的典型行为:把被装饰的函数替换为新函数,二者接收的参数相同,并返回被装饰函数本该的返回值,同时增加一些额外操作。</p>\n<p><strong>func = factorial, factorial = clocked</strong></p>\n<p>clock是装饰器</p>\n<p>factorial是被装饰函数</p>\n<p>clocked是被装饰后的函数</p>\n<p>factorial作为func参数传递给装饰器clock,装饰器clock返回clocked函数并复制给factorial。func是clocked的自由变量,两者构成闭包。</p>\n<p>当调用函数factorial时,实际上调用函数locked,而locked函数中func则为被装饰的函数factorial。</p>\n\n</div>\n</div>\n</div>\n<div class="cell border-box-sizing code_cell rendered">\n<div class="input">\n<div class="prompt input_prompt">In [40]:</div>\n<div class="inner_cell">\n <div class="input_area">\n<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># 实现一个简单的装饰器:调用被装饰的函数时,打印被调用函数的运行时间,传入参数和输出结果。</span>\n\n<span class="kn">import</span> <span class="nn">time</span>\n\n<span class="k">def</span> <span class="nf">clock</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>\n <span class="k">def</span> <span class="nf">clocked</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>\n <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>\n <span class="n">result</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>\n <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span>\n <span class="n">arg_str</span> <span class="o">=</span> <span class="s1">''</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="nb">repr</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span> <span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">])</span>\n <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'time: </span><span class="si">{</span><span class="n">end</span><span class="si">}</span><span class="s1">, args: </span><span class="si">{</span><span class="n">arg_str</span><span class="si">}</span><span class="s1">, result: </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>\n <span class="k">return</span> <span class="n">result</span>\n <span class="k">return</span> <span class="n">clocked</span>\n \n<span class="nd">@clock</span>\n<span class="k">def</span> <span class="nf">factorial</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>\n <span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">n</span> <span class="o"><</span> <span class="mi">2</span> <span class="k">else</span> <span class="n">n</span> <span class="o">*</span> <span class="n">factorial</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>\n</pre></div>\n\n </div>\n</div>\n</div>\n\n</div>\n<div class="cell border-box-sizing code_cell rendered">\n<div class="input">\n<div class="prompt input_prompt">In [39]:</div>\n<div class="inner_cell">\n <div class="input_area">\n<div class=" highlight hl-ipython3"><pre><span></span><span class="n">factorial</span><span class="p">(</span><span class="mi">6</span><span class="p">)</span>\n</pre></div>\n\n </div>\n</div>\n</div>\n\n<div class="output_wrapper">\n<div class="output">\n\n\n<div class="output_area">\n\n <div class="prompt"></div>\n\n\n<div class="output_subarea output_stream output_stdout output_text">\n<pre>time: 7.152557373046875e-07, args: 1, result: 1\ntime: 0.0006625652313232422, args: 2, result: 2\ntime: 0.0007753372192382812, args: 3, result: 6\ntime: 0.0008685588836669922, args: 4, result: 24\ntime: 0.000957489013671875, args: 5, result: 120\ntime: 0.0010552406311035156, args: 6, result: 720\n</pre>\n</div>\n</div>\n\n<div class="output_area">\n\n <div class="prompt output_prompt">Out[39]:</div>\n\n\n\n\n<div class="output_text output_subarea output_execute_result">\n<pre>720</pre>\n</div>\n\n</div>\n\n</div>\n</div>\n\n</div>\n<div class="cell border-box-sizing code_cell rendered">\n<div class="input">\n<div class="prompt input_prompt">In [42]:</div>\n<div class="inner_cell">\n <div class="input_area">\n<div class=" highlight hl-ipython3"><pre><span></span><span class="n">factorial</span><span class="o">.</span><span class="vm">__name__</span> <span class="c1"># 可见factorial是函数locked的引用, 调用factorial(n)即调用locked(n)</span>\n</pre></div>\n\n </div>\n</div>\n</div>\n\n<div class="output_wrapper">\n<div class="output">\n\n\n<div class="output_area">\n\n <div class="prompt output_prompt">Out[42]:</div>\n\n\n\n\n<div class="output_text output_subarea output_execute_result">\n<pre>'clocked'</pre>\n</div>\n\n</div>\n\n</div>\n</div>\n\n</div>\n<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">\n</div><div class="inner_cell">\n<div class="text_cell_render border-box-sizing rendered_html">\n<h2 id="1.-装饰器何时运行?">1. 装饰器何时运行?<a class="anchor-link" href="#1.-装饰器何时运行?">¶</a></h2><p>导入时与运行时:函数装饰器在<strong>导入模块时立即执行</strong>,而被装饰器装饰的函数,只有程序运行时显式调用时才执行。</p>\n<p>装饰器在实际工程中:</p>\n<ul>\n<li><p>通常,装饰器在一个py模块中定义,应用到其他py模块的函数上。</p>\n</li>\n<li><p>通常,装饰器内部绘重新定义一个函数,将其返回。而非作为装饰器参数的函数。</p>\n</li>\n</ul>\n\n</div>\n</div>\n</div>\n<div class="cell border-box-sizing code_cell rendered">\n<div class="input">\n<div class="prompt input_prompt">In [1]:</div>\n<div class="inner_cell">\n <div class="input_area">\n<div class=" highlight hl-ipython3"><pre><span></span><span class="n">registry</span> <span class="o">=</span> <span class="p">[]</span>\n\n<span class="k">def</span> <span class="nf">register</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>\n <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'running register </span><span class="si">{</span><span class="n">func</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>\n <span class="n">registry</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>\n <span class="k">return</span> <span class="n">func</span>\n\n<span class="nd">@register</span>\n<span class="k">def</span> <span class="nf">func1</span><span class="p">():</span>\n <span class="nb">print</span><span class="p">(</span><span class="s1">'running func1'</span><span class="p">)</span>\n\n<span class="nd">@register</span>\n<span class="k">def</span> <span class="nf">func2</span><span class="p">():</span>\n <span class="nb">print</span><span class="p">(</span><span class="s1">'running func2'</span><span class="p">)</span>\n \n<span class="k">def</span> <span class="nf">func3</span><span class="p">():</span>\n <span class="nb">print</span><span class="p">(</span><span class="s1">'running fucn3'</span><span class="p">)</span>\n\n<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>\n <span class="nb">print</span><span class="p">(</span><span class="n">registry</span><span class="p">)</span>\n <span class="n">func1</span><span class="p">()</span>\n <span class="n">func2</span><span class="p">()</span>\n <span class="n">func3</span><span class="p">()</span>\n</pre></div>\n\n </div>\n</div>\n</div>\n\n<div class="output_wrapper">\n<div class="output">\n\n\n<div class="output_area">\n\n <div class="prompt"></div>\n\n\n<div class="output_subarea output_stream output_stdout output_text">\n<pre>running register <function func1 at 0x7fac1e2b6040>\nrunning register <function func2 at 0x7fac1e2b61f0>\n</pre>\n</div>\n</div>\n\n</div>\n</div>\n\n</div>\n<div class="cell border-box-sizing code_cell rendered">\n<div class="input">\n<div class="prompt input_prompt">In [2]:</div>\n<div class="inner_cell">\n <div class="input_area">\n<div class=" highlight hl-ipython3"><pre><span></span><span class="n">registry</span>\n</pre></div>\n\n </div>\n</div>\n</div>\n\n<div class="output_wrapper">\n<div class="output">\n\n\n<div class="output_area">\n\n <div class="prompt output_prompt">Out[2]:</div>\n\n\n\n\n<div class="output_text output_subarea output_execute_result">\n<pre>[<function __main__.func1()>, <function __main__.func2()>]</pre>\n</div>\n\n</div>\n\n</div>\n</div>\n\n</div>\n<div class="cell border-box-sizing code_cell rendered">\n<div class="input">\n<div class="prompt input_prompt">In [4]:</div>\n<div class="inner_cell">\n <div class="input_area">\n<div class=" highlight hl-ipython3"><pre><span></span><span class="n">main</span><span class="p">()</span>\n</pre></div>\n\n </div>\n</div>\n</div>\n\n<div class="output_wrapper">\n<div class="output">\n\n\n<div class="output_area">\n\n <div class="prompt"></div>\n\n\n<div class="output_subarea output_stream output_stdout output_text">\n<pre>[<function func1 at 0x7fac1e2b6040>, <function func2 at 0x7fac1e2b61f0>]\nrunning func1\nrunning func2\nrunning fucn3\n</pre>\n</div>\n</div>\n\n</div>\n</div>\n\n</div>\n<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">\n</div><div class="inner_cell">\n<div class="text_cell_render border-box-sizing rendered_html">\n<h2 id="2.-闭包">2. 闭包<a class="anchor-link" href="#2.-闭包">¶</a></h2><p>多数装饰器会修改被装饰的函数。通常是在装饰器<strong>内部重新定义一个函数</strong>,将其返回,用来替换被装饰的函数。装饰器内部定义函数几乎都需要<strong>闭包</strong>。</p>\n\n</div>\n</div>\n</div>\n<div class="cell border-box-sizing code_cell rendered">\n<div class="input">\n<div class="prompt input_prompt">In [ ]:</div>\n<div class="inner_cell">\n <div class="input_area">\n<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># 设计某商品收盘均价。注:实时增加新价</span>\n\n<span class="c1"># 类写法</span>\n<span class="k">class</span> <span class="nc">Averager</span><span class="p">():</span>\n <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>\n <span class="bp">self</span><span class="o">.</span><span class="n">series</span> <span class="o">=</span> <span class="p">[]</span>\n \n <span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">price</span><span class="p">):</span> <span class="c1"># 可调用对象</span>\n <span class="bp">self</span><span class="o">.</span><span class="n">series</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">price</span><span class="p">)</span>\n <span class="nb">print</span><span class="p">(</span><span class="nb">sum</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">series</span><span class="p">)</span> <span class="o">/</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">series</span><span class="p">))</span>\n \n<span class="n">avg</span> <span class="o">=</span> <span class="n">Averager</span><span class="p">()</span>\n<span class="n">avg</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="c1"># 可调用对象 __call__()</span>\n<span class="n">avg</span><span class="p">(</span><span class="mi">11</span><span class="p">)</span>\n</pre></div>\n\n </div>\n</div>\n</div>\n\n</div>\n<div class="cell border-box-sizing code_cell rendered">\n<div class="input">\n<div class="prompt input_prompt">In [14]:</div>\n<div class="inner_cell">\n <div class="input_area">\n<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># 函数式写法,高阶函数</span>\n\n<span class="k">def</span> <span class="nf">make_averager</span><span class="p">():</span>\n <span class="n">series</span> <span class="o">=</span> <span class="p">[]</span>\n \n <span class="k">def</span> <span class="nf">averager</span><span class="p">(</span><span class="n">price</span><span class="p">):</span>\n <span class="n">series</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">price</span><span class="p">)</span>\n <span class="nb">print</span><span class="p">(</span><span class="nb">sum</span><span class="p">(</span><span class="n">series</span><span class="p">)</span> <span class="o">/</span> <span class="nb">len</span><span class="p">(</span><span class="n">series</span><span class="p">))</span>\n \n <span class="k">return</span> <span class="n">averager</span>\n\n<span class="n">avg</span> <span class="o">=</span> <span class="n">make_averager</span><span class="p">()</span>\n<span class="n">avg</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>\n<span class="n">avg</span><span class="p">(</span><span class="mi">11</span><span class="p">)</span>\n</pre></div>\n\n </div>\n</div>\n</div>\n\n<div class="output_wrapper">\n<div class="output">\n\n\n<div class="output_area">\n\n <div class="prompt"></div>\n\n\n<div class="output_subarea output_stream output_stdout output_text">\n<pre>10.0\n10.5\n</pre>\n</div>\n</div>\n\n</div>\n</div>\n\n</div>\n<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">\n</div><div class="inner_cell">\n<div class="text_cell_render border-box-sizing rendered_html">\n<p>类写法和函数式写法:</p>\n<ul>\n<li><p>共同之处:通过实例化类Averager()和调用make_averager()都会得到一个<strong>可调用对象</strong>。</p>\n</li>\n<li><p>不同之处:如何存历史值price?类self.series,而函数式则存在series中。</p>\n</li>\n</ul>\n<p>而series作为函数make_averager局部变量,在函数返回时局部变量应该销毁。而series相对于make_averager的内部函数averager称为自由变量。</p>\n\n<pre><code> series = []\n\n def averager(price):\n series.append(price)\n print(sum(series) / len(series))</code></pre>\n<p>这个代码块称为闭包。闭包是一种函数,它会保留定义函数时存在的自由变量绑定,即使像make_averager函数返回作用域不存在了,averager函数仍然保留使用这些自由变量绑定。</p>\n<p><strong>重点:只有在嵌套函数中的函数,才可能处理不在全局作用域中的外部变量,相对该函数称为自由变量。而该函数与自由变量称为闭包。</strong></p>\n\n</div>\n</div>\n</div>\n<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">\n</div><div class="inner_cell">\n<div class="text_cell_render border-box-sizing rendered_html">\n<h2 id="3.-关键字nonlocal">3. 关键字nonlocal<a class="anchor-link" href="#3.-关键字nonlocal">¶</a></h2>\n</div>\n</div>\n</div>\n \n\n</body>\n<script type="text/javascript">if (!document.getElementById(\'mathjaxscript_pelican_#%@#$@#\')) {\n var mathjaxscript = document.createElement(\'script\');\n mathjaxscript.id = \'mathjaxscript_pelican_#%@#$@#\';\n mathjaxscript.type = \'text/javascript\';\n mathjaxscript.src = \'//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML\';\n mathjaxscript[(window.opera ? "innerHTML" : "text")] =\n "MathJax.Hub.Config({" +\n " config: [\'MMLorHTML.js\']," +\n " TeX: { extensions: [\'AMSmath.js\',\'AMSsymbols.js\',\'noErrors.js\',\'noUndefined.js\'], equationNumbers: { autoNumber: \'AMS\' } }," +\n " jax: [\'input/TeX\',\'input/MathML\',\'output/HTML-CSS\']," +\n " extensions: [\'tex2jax.js\',\'mml2jax.js\',\'MathMenu.js\',\'MathZoom.js\']," +\n " displayAlign: \'center\'," +\n " displayIndent: \'0em\'," +\n " showMathMenu: true," +\n " tex2jax: { " +\n " inlineMath: [ [\'$\',\'$\'] ], " +\n " displayMath: [ [\'$$\',\'$$\'] ]," +\n " processEscapes: true," +\n " preview: \'TeX\'," +\n " }, " +\n " \'HTML-CSS\': { " +\n " linebreaks: { automatic: true, width: \'95% container\' }, " +\n " styles: { \'.MathJax_Display, .MathJax .mo, .MathJax .mi, .MathJax .mn\': {color: \'black ! important\'} }" +\n " } " +\n "}); ";\n (document.body || document.getElementsByTagName(\'head\')[0]).appendChild(mathjaxscript);\n}\n</script>\n\n </div>\n <!-- /.entry-content -->\n </article>\n </section>\n\n </div>\n <div class="col-sm-3 col-sm-pull-9" id="sidebar">\n <aside>\n<div id="aboutme">\n <p>\n <strong>About Jerry</strong><br/>\n Jerry Su\n </p>\n</div><!-- Sidebar -->\n<section class="well well-sm">\n <ul class="list-group list-group-flush">\n\n<!-- Sidebar/Social -->\n<li class="list-group-item">\n <h4><i class="fa fa-home fa-lg"></i><span class="icon-label">Social</span></h4>\n <ul class="list-group" id="social">\n <li class="list-group-item"><a href="sa517302@mail.ustc.edu.cn"><i class="fa fa-email-square fa-lg"></i> Email</a></li>\n <li class="list-group-item"><a href="https://github.com/jerrylsu"><i class="fa fa-github-square fa-lg"></i> Github</a></li>\n <li class="list-group-item"><a href="https://hub.docker.com/u/jerrysu666"><i class="fa fa-docker-square fa-lg"></i> Docker</a></li>\n </ul>\n</li>\n<!-- End Sidebar/Social -->\n\n<!-- Sidebar/Categories -->\n<li class="list-group-item">\n <h4><i class="fa fa-home fa-lg"></i><span class="icon-label">Categories</span></h4>\n <ul class="list-group" id="categories">\n <li class="list-group-item">\n <a href="/categories/algorithms.html"><i class="fa fa-folder-open fa-lg"></i>Algorithms</a>\n </li>\n <li class="list-group-item">\n <a href="/categories/english.html"><i class="fa fa-folder-open fa-lg"></i>English</a>\n </li>\n <li class="list-group-item">\n <a href="/categories/miscellanea.html"><i class="fa fa-folder-open fa-lg"></i>Miscellanea</a>\n </li>\n <li class="list-group-item">\n <a href="/categories/ml.html"><i class="fa fa-folder-open fa-lg"></i>ML</a>\n </li>\n <li class="list-group-item">\n <a href="/categories/nlp.html"><i class="fa fa-folder-open fa-lg"></i>NLP</a>\n </li>\n <li class="list-group-item">\n <a href="/categories/programming.html"><i class="fa fa-folder-open fa-lg"></i>Programming</a>\n </li>\n <li class="list-group-item">\n <a href="/categories/pytorch.html"><i class="fa fa-folder-open fa-lg"></i>Pytorch</a>\n </li>\n <li class="list-group-item">\n <a href="/categories/rl.html"><i class="fa fa-folder-open fa-lg"></i>RL</a>\n </li>\n <li class="list-group-item">\n <a href="/categories/tensorflow.html"><i class="fa fa-folder-open fa-lg"></i>TensorFlow</a>\n </li>\n <li class="list-group-item">\n <a href="/categories/tools.html"><i class="fa fa-folder-open fa-lg"></i>Tools</a>\n </li>\n </ul>\n</li>\n<!-- End Sidebar/Categories -->\n\n<!-- Sidebar/Tag Cloud -->\n<li class="list-group-item">\n <a href="/"><h4><i class="fa fa-tags fa-lg"></i><span class="icon-label">Tags</span></h4></a>\n <ul class="list-group list-inline tagcloud" id="tags">\n <li class="list-group-item tag-4">\n <a href="/tags/a.html">A*</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/adaboost.html">Adaboost</a>\n </li>\n <li class="list-group-item tag-1">\n <a href="/tags/algorithm.html">Algorithm</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/attention.html">Attention</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/backtracking.html">BackTracking</a>\n </li>\n <li class="list-group-item tag-3">\n <a href="/tags/bert.html">BERT</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/binary-search.html">Binary Search</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/binary-tree.html">Binary Tree</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/blog.html">Blog</a>\n </li>\n <li class="list-group-item tag-3">\n <a href="/tags/breadth-first-search.html">Breadth First Search</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/c.html">C++</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/cart.html">CART</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/cnn.html">CNN</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/conda.html">Conda</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/cygwin.html">Cygwin</a>\n </li>\n <li class="list-group-item tag-1">\n <a href="/tags/deep-learning.html">Deep Learning</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/docker.html">Docker</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/dynamic-programming.html">Dynamic Programming</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/elmo.html">ELMo</a>\n </li>\n <li class="list-group-item tag-2">\n <a href="/tags/english.html">English</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/featuretools.html">Featuretools</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/flask.html">Flask</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/gbdt.html">GBDT</a>\n </li>\n <li class="list-group-item tag-3">\n <a href="/tags/git.html">Git</a>\n </li>\n <li class="list-group-item tag-2">\n <a href="/tags/hadoop.html">Hadoop</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/hexo.html">Hexo</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/kaggle.html">Kaggle</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/leetcode.html">Leetcode</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/linked-list.html">Linked List</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/linux.html">Linux</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/logistic-regression.html">Logistic Regression</a>\n </li>\n <li class="list-group-item tag-1">\n <a href="/tags/machine-learning.html">Machine Learning</a>\n </li>\n <li class="list-group-item tag-1">\n <a href="/tags/nlp.html">NLP</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/pca.html">PCA</a>\n </li>\n <li class="list-group-item tag-1">\n <a href="/tags/python.html">Python</a>\n </li>\n <li class="list-group-item tag-2">\n <a href="/tags/pytorch.html">Pytorch</a>\n </li>\n <li class="list-group-item tag-2">\n <a href="/tags/rasa.html">RASA</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/regularization.html">Regularization</a>\n </li>\n <li class="list-group-item tag-2">\n <a href="/tags/reinforcement-learning.html">Reinforcement Learning</a>\n </li>\n <li class="list-group-item tag-2">\n <a href="/tags/scala.html">Scala</a>\n </li>\n <li class="list-group-item tag-3">\n <a href="/tags/sorting.html">Sorting</a>\n </li>\n <li class="list-group-item tag-2">\n <a href="/tags/spark.html">Spark</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/sql.html">SQL</a>\n </li>\n <li class="list-group-item tag-2">\n <a href="/tags/tensorflow.html">TensorFlow</a>\n </li>\n <li class="list-group-item tag-3">\n <a href="/tags/tools.html">Tools</a>\n </li>\n <li class="list-group-item tag-4">\n <a href="/tags/vim.html">Vim</a>\n </li>\n </ul>\n</li>\n<!-- End Sidebar/Tag Cloud -->\n </ul>\n</section>\n<!-- End Sidebar --> </aside>\n </div>\n </div>\n</div>\n<!-- End Content Container -->\n\n<footer>\n <div class="container-fluid">\n <hr>\n <div class="row">\n <div class="col-xs-10">© 2020 Jerry\n · Powered by <a href="https://github.com/getpelican/pelican-themes/tree/master/pelican-bootstrap3" target="_blank">pelican-bootstrap3</a>,\n <a href="http://docs.getpelican.com/" target="_blank">Pelican</a>,\n <a href="http://getbootstrap.com" target="_blank">Bootstrap</a> </div>\n <div class="col-xs-2"><p class="pull-right"><i class="fa fa-arrow-up"></i> <a href="#">Back to top</a></p></div>\n </div>\n </div>\n</footer>\n<script src="/theme/js/jquery.min.js"></script>\n\n<!-- Include all compiled plugins (below), or include individual files as needed -->\n<script src="/theme/js/bootstrap.min.js"></script>\n\n<!-- Enable responsive features in IE8 with Respond.js (https://github.com/scottjehl/Respond) -->\n<script src="/theme/js/respond.min.js"></script>\n\n\n <script src="/theme/js/bodypadding.js"></script>\n\n\n</body>\n</html>'