day05 函数的进阶
一、命名空间和作用域
- 全局命名空间 在程序从上到下执行的过程中依次加载进内存空间,存放了我们设置的所有变量名和函数名
- 局部命名空间 调用函数的时候才生成,函数调用结束,此处的名称空间被回收,函数内部定义的名字,
- 内置命名空间 python解释器一启动,就可以使用的名字存储在内置命名空间中,启动解释器的时候加载到内存
局部可以使用全局、内置命名空间中的名字
全局可以使用内置命名空间中的名字,但是无法使用局部命名空间中的名字
在内置的命名空间中不能使用局部和全局的名字
正常情况下,执行内置空间中的名字
在全局定义了和内置命名空间中同名的名字时,使用全局的名字
def input(): print("in input now") def func(): input() func() #此时func函数执行时调用的input()函数 是全局命名空间下的input()
先看自己空间是否有,如果有使用自己名称空间下的名字,如果没有则找上一级的名称空间,直到内置空间都没有,则报错
2、函数名的本质
函数名的本质就是内存地址,计算机中变量本质上就是内存地址
函数() 函数的调用
函数的内存地址() 函数的调用
多个函数拥有多个独立的局部命名空间,不相互共享
def func(): print("123") func() #func本质是内存地址 func2=func #函数名也可以赋值 func2() #执行func()函数
- 函数名可以赋值
- 函数名可以作为容器的元素
- 函数名可以作为函数的参数
- 函数名可以作为函数的返回值
3、作用域
- 全局作用域 ——作用在全局——内置和全局名称空间中的名字都属于全局作用域
- 局部作用域 ——作用在局部——函数 局部名空间中的名字属于局部作用域
- global 变量名 在局部中声明变量为全局变量 尽量不要使用 不安全
a=1 #定义一个全局变量 def func():
global a #声明为全局变量 声明过后就可以修改全局变量的值
a+=1 func() print(a)
对于不可变数据类型,在局部可以查看和使用全局作用域的的变量,但是不能直接进行修改,如果要直接修改,需要在程序中局部变量前声明 global a
locals()查看局部作用域中的名称 具体依据locals()的具体位置而定
globals()查看全局和内置命名空间中的名称
4、函数的嵌套和作用域链
1)函数的嵌套调用 只要函数中调用了其他函数就称为嵌套调用
def max(a,b): """ 求两个值的最大值""" return a if a>b else b def the_max(x,y,z): """函数的嵌套调用""" c=max(x,y) #函数的嵌套调用 return max(c,z) print(the_max(1,2,3))
2)函数的嵌套定义
def outer(): def inner(): print("inner") outer()
内部函数可以使用外部函数的变量
nonlocal a 声明了一个上面第一层局部变量
后端语言(python/java/c++/c) 前端语言(html+js+css)
5、闭包
# 闭包 def outer(): """外部函数""" a=1 def inner(): """内部函数""" print(a)
闭包构成的条件
- 必须为嵌套函数
- 内部函数使用了外部函数的变量
def outer(): a=2 def inner(): print(a) #内部函数使用外部函数的变量 a print(inner.__closure__)#打印函数是否为闭包 outer() print(outer.__closure__) #返回None表示不是闭包
闭包的用意场景
对于内部函数,传统的使用方式:
def outer(): a=1 def inner(): """定义一个内部函数""" print(a) inner() #调用内部函数 outer()#调用外部函数
常见闭包形式
def outer(): a=1 def inner(): """定义一个内部函数""" print(a) return inner #返回inner函数名 inn=outer()#调用外部函数 inn()# 在一个函数的外部使用内部的函数 这就是闭包
闭包的小应用
from urllib.request import urlopen def get_url(): url="http://www.xiaohua100.cn/index.html" ret=urlopen(url).read() print(ret) get_url() #调用函数
使用闭包 无需频繁的创建和删除对应的使用变量
from urllib.request import urlopen def get_url(): url="http://www.xiaohua100.cn/index.html" def get(): ret=urlopen(url).read() #获取网页的源码 print(ret) return get get_func=get_url() #调用函数 get_func() get_func() get_func()
二、作业