python基础—函数嵌套与闭包
python基础—函数嵌套与闭包
1、名称空间与作用域
1 名称空间分为:
1 内置名称空间 内置在解释器中的名称
2 全局名称空间 顶头写的名称
3 局部名称空间
2 找一个名称的查找顺序:先在局部名称空间找,再到全局名称空间找,再到内置名称空间
3 Globals() 查看全局名称空间的内容
Locals() 查看局部名称空间的内容
4 全局作用域包含内置名称空间和全局名称空间
局部作用域包含局部名称空间
例
1 查看内建名称空间的内容:
2 作用域
1
2
3
4
5
6
|
x = 1 def foo(): x = 100 print (x) foo() print (x) |
输出结果:
1
2
|
100 1 |
3 一定要注意函数要先定义,后使用
1
2
3
4
5
6
|
def foo(): print ( "from foo" ) bar() def bar(): print ( "from bar" ) foo() |
输出结果:
1
2
|
from foo from bar |
1
2
3
4
5
6
|
def foo(): print ( "from foo" ) bar() foo() def bar(): print ( "from bar" ) |
输出结果:
1
|
NameError: name 'bar' is not defined #报错 |
4 Globals() 查看全局名称空间的内容
Locals() 查看局部名称空间的内容
1
2
3
4
5
6
7
8
9
|
x = 1 def func(): print ( "from func" ) x = 2 print ( globals ()) print ( locals ()) func() print ( globals ()) print ( locals ()) |
输出结果:
1
2
3
4
5
|
from func { 'x' : 1 , '__cached__' : None ... { 'x' : 2 } { 'x' : 1 , '__cached__' : None ... { 'x' : 1 , '__cached__' : None ... |
2、函数嵌套与静态嵌套域
嵌套调用
嵌套调用作用:将一个大的功能细化成各种小的函数功能并调用
1
2
3
4
5
6
7
8
9
10
|
def my_max(x,y): res = x if x >y else y return res print (my_max( 10 , 100 )) def my_max4(a,b,c,d): res1 = my_max(a,b) res2 = my_max(res1,c) res3 = my_max(res2,d) return res3 print (my_max4( 1 , 20 , 3 , 4 )) |
输出结果:
1
2
|
100 20 |
在函数内定义的函数 在外面不能用到
1
2
3
4
5
6
7
|
def f1(): def f2(): def f3(): pass print ( "---->f1" ) f2() f2() |
输出结果:
1
|
NameError: name 'f2' is not defined #报错 |
#嵌套定义
x找值的过程:先在局部名称空间找,再到上一级的局部名称空间找,再到全局名称空间找,再到内置名称空间
1
2
3
4
5
6
7
8
9
10
11
12
13
|
x = 0 def f1(): #x=1 print ( "---f1---" ,x) def f2(): #x=2 print ( "---f2---" ,x) def f3(): #x=3 print ( "---f3---" ,x) f3() f2() f1() |
输出结果:
1
2
3
|
- - - f1 - - - 0 - - - f2 - - - 0 - - - f3 - - - 0 |
3、函数对象
函数被称为第一类对象,函数可以被当做数据传递
(1)函数可以被赋值
直接输出函数名的值: 就是函数在内存中的地址
1
2
3
|
def foo(): print ( "foo" ) print (foo) |
输出结果:
1
|
<function foo at 0x000000DD32CAAD90 > |
函数可以被赋值:将函数名代码的值赋给变量
1
2
3
4
5
|
def foo(): print ( "foo" ) f = foo print (f) f() |
输出结果:
1
2
|
<function foo at 0x0000003AEBEBAD90 > foo |
(2)函数可以作为参数传递
函数可以作为参数传递
1
2
3
4
5
6
|
def foo(): print ( "foo" ) def bar(func): print (func) func() print (bar(foo)) |
输出结果:
1
2
3
|
<function foo at 0x000000A351B4AD90 > foo None |
(3)函数可以作为返回值
函数可以作为函数的返回值
1
2
3
4
5
6
7
8
9
|
def foo(): print ( "foo" ) def bar(func): print (func) func() return func f = bar(foo) print (f) f() |
输出结果:
1
2
3
4
|
<function foo at 0x000000BFD82CAD90 > foo <function foo at 0x000000BFD82CAD90 > foo |
(4)函数可以作为容器类型的元素
函数作为字典的键的值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
def add(): print ( "=======>function add" ) def search(): print ( "=======>function search" ) def delete(): print ( "=======>function delete" ) def change(): print ( "=======>function change" ) def tell_msg(): msg = ''' search:查询 add:添加 delete:删除 change:修改 create:新建 ''' print (msg) def create(): print ( '=======>function create' ) cmd_dic = { 'search' :search, 'add' :add, 'delete' :delete, 'change' :change, 'create' :create } while True : tell_msg() choice = input ( "please input your choice:" ) cmd_dic[choice]() |
4、函数闭包
(1)函数闭定义
闭包:首先必须是内部定义的函数,该函数包含对外部作用域而不是全局作用域名字的引用
定义:内部函数的代码包含对外部函数的代码的引用,但一定不是对全局作用域的引用
闭包的基本形式是:
在函数F1中,定义F2,F2只能引用F1定义的变量,之后F1函数返回F2的函数名字
这样就保证了可以将F1的执行结果赋予给一个变量,该变量可以在之后的任何时刻随时可以运行
使用闭包的好处:自带状态即变量,可以不用传参就用,方便。
闭包(closure)是函数式编程的重要的语法结构。不同的语言实现闭包的方式不同。Python以函数对象为基础,为闭包这一语法结构提供支持的 (我们在特殊方法与多范式中,已经多次看到Python使用对象来实现一些特殊的语法)。Python一切皆对象,函数这一语法结构也是一个对象。在函数对象中,我们像使用一个普通对象一样使用函数对象,比如更改函数对象的名字,或者将函数对象作为参数进行传递。
(2)简单闭包举例
1
2
3
4
5
6
7
8
9
10
|
x = 1000 def f1(): x = 1 def f2(): print (x) return f2 f = f1() print (f) x = 123 f() |
输出结果:
1
2
|
<function f1.< locals >.f2 at 0x000000C02BD1AF28 > 1 |
(3)闭包的__closure__变量
闭包都有__closure__属性
__closure__对象会返回闭包应用外围作用域的变量信息。f.__closure__保存外围作用域的变量内存地址,f.__closure__[0].cell_contents存放的是外围作用域的变量的值。
对于那些不是闭包的函数对象来说,__closure__ 属性值为 None。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
x = 1 def f1(): x = 1000 y = 2 def f2(): y print (x) return f2 f = f1() #f ---> 内部的函数f2 f() print (f.__closure__) print (f.__closure__[ 0 ]) print (f.__closure__[ 0 ].cell_contents) print (f.__closure__[ 1 ]) print (f.__closure__[ 1 ].cell_contents) |
输出结果:
1
2
3
4
5
6
|
1000 (<cell at 0x000000429E165D68 : int object at 0x000000429E0A9EB0 >, <cell at 0x000000429E165D98 : int object at 0x0000000059C0EF50 >) <cell at 0x000000429E165D68 : int object at 0x000000429E0A9EB0 > 1000 <cell at 0x000000429E165D98 : int object at 0x0000000059C0EF50 > 2 |
举例:__closure__ 属性值为 None
1
2
3
4
5
6
7
8
|
x = 1 def f1(): def f2(): print (x) return f2 f = f1() #f ---> 内部的函数f2 f() print (f.__closure__) |
输出结果为:
1
2
|
1 None |
(4)闭包应用
Windows中cmd中执行pip install requests 安装requests库件
爬baidu网站的程序
1
2
3
4
5
|
from urllib.request import urlopen def get(url): return urlopen(url).read() print (get( 'http://www.baidu.com' )) print (get( 'http://www/python.org' )) |
将上面”爬百度”的程序修改成闭包模式:
1
2
3
4
5
6
7
8
9
|
from urllib.request import urlopen def f1(url): def f2(): print (urlopen(url).read()) return f2 baidu = f1( 'http://www.baidu.com' ) python = f1( 'http://www.python.org' ) baidu() python() |