Python基础10(函数命名空间及作用域)
函数进阶
命名空间和作用域
内置命名空间----python解释器
全局命名空间---我们写的代码但不是函数中的代码
是在程序从上到下被执行的过程中依次加载进内存的
放置了我们设置的所有变量名和函数名
局部命名空间-------函数
在局部:可以使用全局、内置命名空间中的名字
在全局:可以使用内置命名空间中的名字,但不能使用局部命名空间中的名字
在内置:不能使用局部和全局的名字

ps注意
1》在正常情况下,直接使用内置的名字
2》当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字
3》当我们有的时候,就不找我的上一级要了
4》如果自己没有就找上一级要
1 def max(l): 2 print('in max func') 3 print(max([1,2,3]))
5》多个函数应该拥有多个独立的局部名字空间,不相互共享
1 def func(s): # func ---> 函数的内存地址 2 # 函数名()-----> 函数的调用 3 # 函数的内存地址()-----> 函数的调用 4 print('in max func') 5 print(func)
作用域
作用域两种
全局作用域---作用在全局---内置和全局名字空间中的名字都属于全局作用域 --------globals()
局部作用域---作用在局部---函数(局部名字空间中的名字属于局部作用域) ---------locals()
ps:注意
对于不可变数据类型,在局部可以查看全局作用域的变量,但不能直接修改,如果想要修改,需要在程序的一开始添加global声明
如果在一个局部(函数)内声明一个global变量,那么这个变量在局部的所有操作将对全局的变量有效
1 a = 1 2 def func(): 3 global a 4 a = 2 5 6 func() 7 print(a) # a = 2
1 # a = 1 2 # b = 2 3 # def func(): 4 # x = 'aaa' 5 # y = 'bbb' 6 # print(locals()) 7 # print(globals()) 8 # 9 # func() 10 # print(globals()) 11 # print(locals()) #本地的 12 13 #globals 永远打印全局的名字 14 #locals 输出什么 根据locals所在的位置
函数的嵌套和作用域链
函数的嵌套调用
1 def max2(x, y): 2 i = y if x < y else x 3 return i 4 def max1(a,b,c,d): 5 s1 = max2(a, b) # 函数的嵌套调用 6 s2 = max2(c, s1) 7 s3 = max2(d, s2) 8 return s3 9 print(max(1,2,3,4))
函数嵌套定义
1 def f1(): # 声明函数f1 2 print("in f1") 3 def f2(): # 声明函数f2 4 print("in f2") 5 6 f2() # 调用函数f2 7 f1() # 调用函数f1
内部函数可以使用外部函数的变量
1 a = 1 2 def outer(): 3 a = 1 4 def inner(): 5 a = 2 6 def inner2(): 7 nonlocal a #声明了一个上面第一层局部变量 8 a += 1 #不可变数据类型的修改 9 inner2() 10 print('##a## : ', a) # ##a## : 3 11 inner() 12 print('**a** : ',a) # **a** : 1 13 14 outer() 15 print('全局 :',a) # 全局 : 1
nonlocal
nonlocal 只能用于局部变量 找上层中离当前函数最近一层的局部变量
声明了nonlocal的内部函数的变量修改会影响到 离当前函数最近一层的局部变量 对全局无效 对局部 也只是对 最近的 一层 有影响
1 a = 0 2 def outer(): 3 a = 1 4 def inner(): 5 a = 2 6 def inner2(): 7 nonlocal a 8 print(a) 9 inner2() 10 inner() 11 outer()
函数名的本质
函数名本质上就是函数的内存地址
1.可以被引用
1 def func(): 2 print('in func') 3 f = func 4 print(f)
2.可以被当作容器类型的元素
1 def f1(): 2 print('f1') 3 4 5 def f2(): 6 print('f2') 7 8 9 def f3(): 10 print('f3') 11 12 l = [f1,f2,f3] 13 d = {'f1':f1,'f2':f2,'f3':f3} 14 #调用 15 l[0]() 16 d['f2']()
3.可以当作函数的参数和返回值
第一类对象(first-class object)指
1.可在运行期创建
2.可用作函数参数或返回值
3.可存入变量的实体。
闭包
闭包函数:
内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
函数内部定义的函数称为内部函数
由于有了作用域的关系,我们就不能拿到函数内部的变量和函数了。如果我们就是想拿怎么办呢?返回呀!
我们都知道函数内的变量我们要想在函数外部用,可以直接返回这个变量,那么如果我们想在函数外部调用函数内部的函数呢?
是不是直接就把这个函数的名字返回就好了?
这才是闭包函数最常用的用法
1 def func(): 2 name = 'eva' 3 def inner(): 4 print(name) 5 return inner 6 7 f = func() 8 f()
判断闭包函数的方法__closure__
1 #输出的__closure__有cell元素 :是闭包函数 2 def func(): 3 name = 'eva' 4 def inner(): 5 print(name) 6 print(inner.__closure__) 7 return inner 8 9 f = func() 10 f() 11 12 #输出的__closure__为None :不是闭包函数 13 name = 'egon' 14 def func2(): 15 def inner(): 16 print(name) 17 print(inner.__closure__) 18 return inner 19 20 f2 = func2() 21 f2()
闭包函数获取网络应用
1 from urllib.request import urlopen 2 3 def index(): 4 url = "http://www.xiaohua100.cn/index.html" 5 def get(): 6 return urlopen(url).read() 7 return get 8 9 xiaohua = index() 10 content = xiaohua() 11 print(content) 12 13 闭包函数获取网络应用
PS 默认函数陷阱问题
1 def qqxing(l = []): 2 l.append(1) 3 print(l) 4 5 qqxing() #[1] 6 qqxing() #[1,1] 7 qqxing() #[1,1,1] 8 9 # 如果默认参数的值是一个可变数据类型, 10 # 那么每一次调用函数的时候, 11 # 如果不传值就公用这个数据类型的资源

浙公网安备 33010602011771号