首页 » 编程 » Python » 正文

闭包

day21

闭包:在内嵌函数中,首先必须是内部定义的函数,该函数包含对外部作用域而不是全局作用域名字的引用


如下例子:

x = 100  # 全局作用域名字
def f1():
    x = 1  # x = 1 对f2而言就是外部作用域名字
    y = 2
    def f2():
        print(x)
        y
    return f2
f = f1()
print(f)  # 得到的是f2的内存地址
f()   # 这里输出结果是1,作用域在定义阶段就已经确立,跟调用的时候的位置没有关系

# tips: 可以使用 f.__closure__ 可说明就是闭包
print(f.__closure__)  # 可得出一个元组,元素包括内部函数引用外部作用域的内存地址,f2没有返回结果则返回的None
print(f.__closure__[0])  # 可得出元组中第一个元素的地址
print(f.__closure__[0].cell_contents)  # 可得出第一个元素x的地址的值,输出为 1
print(f.__closure__[1].cell_contents)  # 可得出第一个元素y的地址的值,输出为 2

输出结果:

<function f1.<locals>.f2 at 0x0000024794D398C8>
1
(<cell at 0x0000024794CA55B8: int object at 0x00000000648C60E0>, <cell at 0x0000024794CA55E8: int object at 0x00000000648C6100>)
<cell at 0x0000024794CA55B8: int object at 0x00000000648C60E0>
1
2



举个例子(爬虫)来说明作用:

首先安装requests模块:

pip install requests

import requests
print(requests.get("http://www.baidu.com"))   # 得到返回值 <Response [200]>
print(requests.get("http://www.baidu.com").text)  # 得到页面的html代码


再次安装urlopen模块:

pip install urlopen


from urllib.request import urlopen

def get(url):
    # print(url)   # 得到传入的url http://www.baidu.com
    # print(urlopen(url))  # 得到内存地址 <http.client.HTTPResponse object at 0x000001784B748978>
    # print(urlopen(url).read())  # 得到html代码
    return urlopen(url).read()   # 返回html代码
print(get("http://www.baidu.com"))  # 打印返回值
print(get("http://www.python.org"))  # 打印返回值


爬python,要用的时候直接python()调用即可,对于使用者而言,不用关心里面的状态,对使用者隐藏。闭包函数除了返回函数体的功能外还包含对外部作用域的状态。

from urllib.request import urlopen
def f1(url):
    def f2():
        print(urlopen(url).read())
    return f2
python=f1("http://www.python.org")
python  # 没加括号,不会使用
python()  # 加上括号,开始调用使用





发表评论

*