python中函数嵌套及作用域链和闭包

引子

 1 def max(a,b):
 2     '''
 3     求出a,b中的最大值
 4     :return: 最大的一项值
 5     '''
 6     return a if a>b else b
 7 
 8 def the_max(x,y,z):
 9     '''
10     求出x,y,x中的最大值
11     :return: 最大的一项值
12     '''
13     c = max(x,y)
14     return max(c,z)
15 print(the_max(1,2,3))

1:嵌套的定义

1 def outer():
2     def inner():
3         print('inner')
4     inner()
5 outer()

1.1 内部函数可以使用外部函数的变量

 1 def outer():
 2     a = 1
 3     def inner():
 4         b = 2
 5         print(a)
 6         print('inner')
 7         def inner2():
 8             print(a,b)
 9             print('inner')
10         inner2()
11     inner()
12 outer()          #输出结果:1
13                  #          inner
14                  #          1 2
15                  #          inner

1.2  在函数内部,不可变数据类型只能查看不能修改

 1 def outer():
 2     a = 1
 3     def inner():
 4         b = 2
 5         print(a)
 6         print('inner')
 7         def inner2():
 8             a += 1
 9             print(a)
10         inner2()
11     inner()
12 outer()              #输出结果:UnboundLocalError: local variable 'a' referenced before assignment

 

1.3若是要修改的话---global(全局变量的修改) nonlocal(局部变量的修改)

  nonlocal:如果局部变量里面没有,但是全局变量里面有,那么则报错,nonlocal只能用于局部变量,找上一层中离当前函数最近的一层的局部变量

  

 1 a = 1        #全局a
 2 def outer():
 3     a = 1     #局部a
 4     def inner():
 5         b = 2
 6         print(a)
 7         print('inner')
 8         def inner2():
 9             nonlocal a     #nonlocal 声明一个局部变量
10             a += 1
11             print('局部',a)
12         inner2()
13     inner()
14 outer()
15 print('全局',a)  #输出结果:1
16                  #          inner
17                  #          局部 2
18                  #          全局 1

global

 1                  #
 2 a = 1        #全局a
 3 def outer():
 4     a = 1     #局部a
 5     def inner():
 6         b = 2
 7         print(a)
 8         print('inner')
 9         def inner2():
10             global a     #global 声明一个全局变量
11             a += 1
12             print('小局部:',a)     #打印的是全局的a
13         inner2()
14     inner()
15     print('局部:',a)
16 outer()
17 print('全局:',a)  #输出结果:1
18                   #          inner
19                   #          小局部: 2
20                   #          局部: 1
21                   #          全局: 2

2:函数名的几个小用法

2.1 函数名可以赋值

def func():
    print('123')

#func  函数名就是变量地址
func2 = func
func2()        #输出结果:123

2.2 函数名可以作为容器类型的元素

1 l = [func,func2]
2 print(l)
3 for i in l:
4     i()        #输出结果:[<function func at 0x036B9810>, <function func at 0x036B9810>]
5                #          123
6                #          123

2.3  函数名可以作为函数的参数

1 def func():
2     print(123)
3 
4 def func2(f):
5     f()
6 func2(func)        #输出结果:123

2.4   函数名可以作为返回值

1 def func():
2     print(123)
3 
4 def func2(f):
5     return f
6 
7 res = func2(func)
8 res()                #输出结果:123

3:闭包:嵌套函数,内部函数调用外部函数的变量

1 def outer():
2     a = 1
3     def inner():
4         print(a)

闭包的判断:

1 def outer():
2     a = 1
3     def inner():
4         print(a)
5     print(inner.__closure__)
6 outer()            # 输出结果:(<cell at 0x03DAEF50: int object at 0x54ED3900>,)
7                    # 只要有cell这玩意儿,就说明是闭包

1 def outer():
2     a = 1
3     def inner():
4         print(a)
5     print(inner.__closure__)
6 outer()
7 print(outer.__closure__) # 输出结果:(<cell at 0x03DAEF50: int object at 0x54ED3900>,)
8                          # 输出结果:None  (outer函数非闭包)

闭包常见的调用方法:在一个函数外部使用它函数内部的函数(重要)

1 def outer():
2     a = 1
3     def inner():
4         print(a)
5     return inner
6 inn = outer()
7 inn()
8 #只要后面有对inn()函数的引用,则outer内inner外的进程不会立马结束,
9 # 好处是没必要每次调用outer都重新生成

闭包的应用举例:

 1 from urllib.request import urlopen
 2 
 3 def get_url():
 4     url = 'https://y.qq.com'
 5     def get():
 6         ret = urlopen(url).read()
 7         print(ret)
 8     return get
 9 
10 get_func = get_url()
11 get_func()
12 #没必要每次使用时都在重新生成变量url,这样的话,可以节约资源

猜你喜欢

转载自www.cnblogs.com/rcat/p/9313706.html