函数进阶
一、命名空间和作用域
1.命名空间
分为内置命名空间(最上层),全局命名空间(低一层)、局部命名空间(底层)
# 内置命名空间:不能使用全局、局部的变量(不依赖) # python解释器启动就可用,例如print,input,list,tuple,when等 # 内置的名字在启动解释器的时候被加载进内存。 # 全局命名空间:可以使用内置,不能使用全局 # 程序执行过程中依次加载进内存。防止设置的所有函数名和变量名 # 局部命名空间:可以使用全局、内置.并且多个局部命名空间不能串用 # 函数内部定义的变量名,当调用函数时才会产生名称空间,函数调用结束,命名空间就回收 # 如果在全局名字空间定义的变量名是关键字(如input或max)和内置名字空间中同名的名字时 # 那么调用的就是自己定义的函数
#局部的命名空间时,假如使用一个已经自定义,但是同时也是关键字的名字,那么会向上级,就是全局变量找,可以找到。 #如果在内置命名空间都没有,就会报错 #函数名去掉括号,就指向函数的内存地址,加括号就是调用执行。也就是内存地址+()=执行
2.作用域
#作用域 #全局作用域:作用在全局-内置和全局名字空间中的名字都属于全局作用域 #局部作用域:作用在局部-函数,局部名字空间中的名字 #对于不可变数据类型,在局部只能查看不能直接修改,想修改需要在程序一开始添加global声明 #局部作用域中的使用locals函数可以查看当前函数内所有的名字 #globals永远打印全局的名字,locals看当前在全局还是局部打印当前的所有名字 # #global不是特别安全,可以通过接收参数和传参,更安全a=func(a),就可以修改了
二、函数进阶
1.函数嵌套
# 函数的嵌套定义 def outer(): def inner(): print("c") outer() #什么都不会发生,并没有调用inner(),inner就会消失 def outer(): a = 'n' def inner(): print("c") print(a) #会打印,因为上级有a inner() outer() #打印 #c #n
2.闭包
#函数的闭包 #闭包:嵌套函数,内部函数调用外部函数的变量 def outer(): a=1 def inner(): print(a) #只要用上外部函数的变量,就是闭包 print(inner.__closure__) outer() print(outer.__closure__) def outer(): a=1 def inner(): print(a) return inner() inx=outer() #函数作为返回值 inx #在函数外部使用函数内部
闭包的应用:节省资源
闭包的示例:爬取网络页面
#闭包的应用(爬虫示例) #import urllib #模块 from urllib.request import urlopen ret = urlopen('http://www.baidu.com').read()#要联网 print(ret) #检查console,查看网页源代码 def get_url(): url='http://www.baidu.com' #flag1 def get(): ret=urlopen(url).read() print(ret) return get get_func=get_url() #节省资源,就不用生成外部的flag1的资源 # 相当于把源码获得,类似wget,只是将网页down下来