Python_day11_闭包函数详解编程语言

一、【函数名】

1)函数名本质上它也是一种变量,特殊的变量; 
(碰到同名其它变量,依照从上往下的代码执行赋值。) 
单独打印函数名,输出的是它对应的内存地址: 
 
例: 
def funcl(): 
    print(666) 
print(funcl) 
 
返回如下: 
<function funcl at 0x0000000000DF5488> 
 
2)函数名可以赋值给其它变量名; 
def funcl(): 
    print(666) 
 
f1 = funcl 
f1() 
 
666 
 
3)函数名可以作为容器类的元素; 
def funcl(): 
    print(666) 
# print(funcl) 
 
f1 = funcl 
f1() 
 
def f2(): 
    print(222) 
 
def f3(): 
    print(333) 
 
def f4(): 
    print(444) 
 
li =[f1, f2, f3, f4] 
print(li) 
 
# 返回的是对应的内存地址 
 
for i in li: 
    i() 
 
# 依次执行函数,可以看到函数名作为列表(容器)的元素也是可以的。 
666 
222 
333 
444 
 
4)函数名可以作为参数; 
def f1(): 
    print(666) 
 
def f2(a): 
    a() 
    print(777) 
     
f2(f1)                                                                                           
 
输出的结果: 
666 
777 
 
上例中f1函数名是作为f2函数的参数。 
 
5)函数名可以作为函数的返回值。 
例: 
def f1(): 
    print(666) 
 
def f2(): 
    return f1 
 
f2()() 
 
# 输出666 
 
def f3(): 
    def f4(): 
        print(777) 
    return f4 
 
f3()() 
 
#输出 777

以上例子可以看出函数名也可以作为函数的返回值,而且通过return返回的嵌套函数可以调用执行成功。
像上例中的f3()()如果改成f4()是会报错:NameError: name ‘f4’ is not defined,原因就是全局命名空间中找不到f4()函数定义。所以这是命名空间很神奇的一个地方。

二、【闭包函数】

内层函数对外层函数,非全局变量的引用。
判断闭包函数:函数名.closure(),返回的值中有cell这个元素表示该函数为闭包函数。
闭包函数的机制:当函数开始执行时,如果遇到了闭包,在内存当中会为闭包开辟一个内存空间,用于将闭包中的变量等值放入其中,并不会随着函数的执行完毕而消失。

函数内部定义的函数称为内部函数

主要作用有:
1)缓存,节省内存空间;例如爬虫用,(不断重复爬取同一网页的情况下)
2)装饰器,最能完整体现出闭包的作用。

由于作用域的关系,
我们不能直接拿到函数内部的变量和函数了。如果我们就是想拿怎么办呢?通过返回值!
函数内的变量要想在函数外部用,可以直接返回这个变量,那么如果想在函数外部调用函数内部的函数呢?
是不是直接就把这个函数的名字返回就好了?
这才是闭包函数最常用的用法。所以这也是装饰器之所以是闭包函数最能完整体现用法的原因。

例:闭包函数的运用,引用外层的函数。 
def func(): 
    name = 'eva' 
    def inner(): 
        print(name) 
    return inner 
 
func() # 直接执行func,并没有调用到func里面的inner函数,不会输出eva 
f = func() 
f() # 相当于是执行func()(),而func()中返回了inner函数, 
    # 所以又相当于是在func函数体内部中执行func(inner),所以就能正常执行了。 
 
#输出 
 
eva 
 
例:判断是否为闭包函数 
函数名.__closure__() 
#输出的__closure__有cell元素 :是闭包函数 
def func(): 
    name = 'eva' 
    def inner(): 
        print(name) 
    print(inner.__closure__) 
    return inner 
 
f = func() 
f() 
 
print('我是华丽的分割线'.center(30, '-')) 
 
#输出的__closure__为None :不是闭包函数(没有引用外层,试图引用的是全局的变量,所以不为闭包) 
name = 'egon' 
def func2(): 
    def inner(): 
        print(name) 
    print(inner.__closure__) 
    return inner 
 
f2 = func2() 
f2() 
 
(<cell at 0x0000000000BF9138: str object at 0x0000000000BE0D18>,) 
eva 
-----------我是华丽的分割线----------- 
None 
egon 
 
例:闭包的嵌套(两层,还可以嵌套到三层,一般三层己够满足需要了) 
下面是借助不断给函数名赋值成变量来调用嵌套的函数的,这个方法其实在说到装饰器时会用上,为什么要简化成一个变量名()的方式,就是为了装饰其他函数用(不用改变其他函数的表现形式) 
def wrapper(): 
    money = 1000 
    def func(): 
        name = 'eva' 
        def inner(): 
            print(name, money) 
        return inner 
    return func 
 
f = wrapper() 
i = f() 
i() 
 
eva 1000 
 
例:闭包函数获取网络应用(简单爬虫雏形) 
下例为我爬取我的个人wordpress博客首页所用的简单代码, 
到最后的内容需要用到decode解码才能看到页面源代码。 
还可以更进一步使用文件操作写入到文件。 
from urllib.request import urlopen 
 
def index(): 
    url = "https://www.tielemao.com" 
    def get(): 
        return urlopen(url).read() 
    return get 
 
tielemao = index() 
content = tielemao() 
print(content.decode('utf-8')) 
 
写到文件上保存: 
from urllib.request import urlopen 
 
def index(): 
    url = "https://www.tielemao.com" 
    def get(): 
        return urlopen(url).read() 
    return get 
 
tielemao = index() 
content = tielemao() 
# print(content.decode('utf-8')) 
s = content.decode('utf-8') 
with open('tielemao_index.html', encoding='utf-8', mode='a') as f1: 
    f1.write(s)

Python_day11_闭包函数详解编程语言

end
2018-4-3

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/12765.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论