【函数闭包的理解】
最近学到 函数 闭包的时候,似懂非懂、迷迷糊糊的样子,很是头疼,今天就特意查了下关于闭包的知识,现将我自己的理解分享如下!
一、python 闭包定义
首先,关于闭包,百度百科是这样解释的:
闭包是指可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。
当然,这种学术性的解释对于我们小白来说,只能是更加的晦涩难懂。
从python对闭包的定义来说:
必须是内部定义的函数,该函数包含对外部作用域而不是全局作用域名字的引用!
可能这么说还是有点难理解,那咱们换一种方式理解:
python中的闭包从表现形式上可以解释为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包.
举个简单的例子来说明,可能会好理解一些:
def f1():
x = 12
def f2():
print(x)
return f2
f = f1()
print(type(f))
print(f)
f()
代码执行之后的结果如下:
<class 'function'>
<function f1.<locals>.f2 at 0x00000000028EC9D8>
12
结合这段简单的代码和定义来说明闭包:
如果在一个内部函数里:f2()就是这个内部函数,
对在外部作用域(但不是在全局作用域)的变量进行引用:x就是被引用的变量,x在外部作用域f1()里面,但不在全局作用域里。
则这个内部函数f2()就是一个闭包。
从函数的定义角度出发:函数可以嵌套使用,可以把函数当成参数或返回值进行传递,函数也可以作为容器类型的元素,作为一个变量可以去赋值。
在这个简单的例子当中,函数f1()中嵌套定义另一个函数f2(),内部的函数f2()引用了外部函数f1()的变量,函数f2()被当成夹带外部变量的 对象 返回给f1(),这样就形成一个闭包函数。
实例化输出的时候 定义的 f=f1()中, 其实 f 就是函数f2()(不准确但是好理解)。这里需要注意的是,f 是一个函数名,加上()就能当作函数来用了。(因为f2()返回的是一串函数执行过程的包)
二、闭包的用途
1、闭包就是为了不动原函数里面的代码,还要给它增加‘新功能’的一种手段。
最直接的例子就是爬取网站代码的闭包函数,不使用的时候,不用执行闭包函数,当需要爬取网站数据时,直接将定义的函数名后加上(),当作函数来使用。
执行结果如下:
<function get.<locals>.index at 0x0000000002E45B70> b'<!doctype html>\n<!--[if lt IE 7]> <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9"> <![endif]-->\n<!--[if IE 7]> <html class="no-js ie7 lt-ie8 lt-ie9"> <![endif]-->\n<!--[if IE 8]> <html class="no-js ie8 lt-ie9"> <![endif]-->\n<!--[if gt IE 8]><!--><html class="no-js" lang="en" dir="ltr"> <!--<![endif]-->\n\n<head>\n <meta charset="utf-8">\n <meta http-equiv="X-UA-Compatible" content="IE=edge">\n\n <link rel="prefetch" href="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js">\n\n <meta name="application-name" content="Python.org">\n <meta name="msapplication-tooltip" content="The official home of the Python Programming Language">\n <meta name="apple-mobile-web-app-title" content="Python.org">\n <meta name="apple-mobile-web-app-capable" content="yes">\n <meta name="apple-mobile-web-app-status-bar-style" content="black">\n\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <meta name="HandheldFriendly" content="True">\n <meta name="format-detection" content="telephone=no">\n <meta http-equiv="cleartype" content="on">\n <meta http-equiv="imagetoolbar" content="false">\n\n <script src="/static/js/libs/modernizr.js"></script>\n\n <link href="/static/stylesheets/style.css" rel="stylesheet" type="text/css" title="default" />\n <link href="/static/stylesheets/mq.css" rel="stylesheet" type="text/css" media="not print, braille, embossed, speech, tty" />\n \n\n <!--[if (lte IE 8)&(!IEMobile)]>\n <link href="/static/stylesheets/no-mq.css" rel="stylesheet" type="text/css" media="screen" />\n \n \n <![endif]-->\n\n \n <link rel="icon" type="image/x-icon" href="/static/favicon.ico">\n <link rel="apple-touch-icon-precomposed" sizes="144x144" href="/static/apple-touch-icon-144x144-precomposed.png">\n <link rel="apple-touch-icon-precomposed" sizes="114x114" href="/static/apple-touch-icon-114x114-precomposed.png">\n <link rel="apple-touch-icon-precomposed" sizes="72x72" href="/static/apple-touch-icon-72x72-precomposed.png">\n <link rel="apple-touch-icon-precomposed" href="/static/apple-touch-icon-precomposed.png">\n <link rel="apple-touch-icon" href="/static/apple-touch-icon-precomposed.png">\n\n \n <meta name="msapplication-TileImage" content="/static/metro-icon-144x144-precomposed.png"><!-- white shape -->\n <meta name="msapplication-TileColor" content="#3673a5"><!-- python blue -->\n <meta name="msapplication-navbutton-color" content="#3673a5">\n\n <title>Welcome to Python.org</title>\n\n <meta name="description" content="The official home of the Python Programming Language">\n <meta name="keywords" content="Python programming language object oriented web free open source software license documentation download community">\n\n \n <meta property="og:type" content="website">\n <meta property="og:site_name" content="Python.org">\n <meta property="og:title" content="Welcome to Python.org">\n <meta property="og:description" content="The official home of the Python Programming Language">\n \n <meta property="og:image" content="https://www.python.org/static/opengraph-icon-200x200.png">\n <meta property="og:image:secure_url" content="https://www.python.org/static/opengraph-icon-200x200.png">\n \n <meta property="og:url" content="https://www.python.org/">\n\n <link rel="author" href="/static/humans.txt">\n\n \n\n \n <script type="application/ld+json">\n {\n "@context": "http://schema.org",\n "@type": "WebSite",\n "url": "https://www.python.org/",\n "potentialAction": {\n "@type": "SearchAction",\n "target": "https://www.python.org/search/?q={search_term_string}",\n "query-input": "required name=search_term_string"\n }\n }\n </script>\n\n \n <script type="text/javascript">\n var _gaq = _gaq || [];\n _gaq.push([\'_setAccount\', \'UA-39055973-1\']);\n _gaq.push([\'_trackPageview\']);\n\n (function() {\n var ga = document.createElement(\'script\'); ga.type = \'text/javascript\'; ga.async = true;\n ga.src = (\'https:\' == document.location.protocol ? \'https://ssl\' : \'http://www\') + \'.google-analytics.com/ga.js\';\n var s = document.getElementsByTagName(\'script\')[0]; s.parentNode.insertBefore(ga, s);\n })();\n </script>\n \n</head>\n\n<body class="python home" > http://www.python.org