python 函数进阶与闭包
2017-07-30 11:38
204 查看
函数的命名空间和作用域
命名空间
定义:可以理解为一个容器,在这个容器中可以装许多个名字。不同容器中的同名的名字是不会相互冲突
命名空间的三种形式
内置命名空间 全局命名空间 局部命名空间 内置 在启动解释器的时候生成的,存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法 全局 文件级别定义的名字都会存放在全局命名空间,执行python文件时会产生,文件执行完毕就会失效文件级别:定义的名字:顶头写的没有缩进的名字 局部级别:定义在函数内部的名字,只在调用函数时才会生效,函数调用完毕就会失效
三种命名空间之间的加载与取值顺序
加载顺序:
内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)
取值顺序:
(1) 在局部调用:局部命名空间->全局命名空间->内置命名空间
1 x = 1 2 def f(x): 3 print(x) 4 print(10) 结果为10
注释:执行代码 第一步x=1 定义函数f并传入形参x 第三步 打印x 第四步
(2)在全局调用:全局命名空间->内置命名空间
1 x = 1 2 def f(x): 3 print(x) 4 5 f(10) 6 print(x)
函数的作用域:
作用域定义:作用域就是作用范围
作用域分类
1 全局作用域: 包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效 2 局部作用域: 包含局部名称空间,只能在局部范围内生效
作用域中的关键字
globals查看内置和全局的所有变量名字,
locals查看局部的所有变量名字:当把locals放到全局的位置时可以查看全局的所有变量名字,当把locals放到局部的位置时就可以查看局部范围的所有变量名字
作用域的作用范围
globals 全局的作用范围 locals 局部的作用范围在局部调用globals和locals 1 def func():
2 a = 12 3 b = 20 4 print(locals()) 5 print(globals()) 6 7 func()
global关键字 能不用尽量不去用
1 a = 10 现在a=10 2 def func(): 3 global a 使用global将变量改变为全局变量 4 a = 20 将其赋值为20 6 print(a) 打印函数func中的变量a=20 7 func() 8 print(a) 全局变量a初始值为10,经过globals改变以后值为20
所以结果 10 20
作用域总结:
站在全局的角度,从使用名字来看:如果全局有:用全局的,如果全局没有:用内置的
函数的嵌套和作用域链
函数嵌套的作用
作用:为了保护内部函数,确定内部函数只能在外部函数中被调用
函数的嵌套调用
1 def f1():2 print('f1') 3 def f2(): 4 a = 10 5 f1() 6 f2() 7 #代码从上到下读取,f2()调用会调用f2()函数体的内容,最后发现f1()然后调用f1()开始执行函数体的内容最后输出f1
示例二
1 def animal(): 2 def tiger(): 3 print('bark') 4 print('eat') 5 tiger() 6 animal() #函数嵌套调用 7 8 9 eat 10 bark
函数的嵌套定义
1 def f1(): 2 def f2(): 3 def f3(): 4 print("in f3") 5 print("in f2") 6 f3() 7 print("in f1") 8 f2() 9 10 f1()
函数的作用域链
1 def f1(): 2 a = 1 3 def f2(): 4 print(a) 5 f2() 6 7 f1() 结果为11 def f1():
2 a = 1 3 def f2(): 4 a = 2 5 f2() 6 print('a in f1 : ',a) 7 8 f1() 结果 1
nonlocal关键字
1 def f1():2 a = 1 nolocal向上改变一层到这里,a的值被改变为2 3 def f2(): 4 nonlocal a 改变变量a的值并且只可以向上改变一层 5 a = 2 改变后的值为2 6 f2() 7 print('a in f1 : ',a) 8 9 f1() 结果 2 2 10 #函数会使用自己本身的a的赋值,f2()函数体里面的赋值用完会从内存删除掉,想保留要加入nonlocal 加变量名才能会取f2()函数体里a的赋值
函数名的本质
函数名本质上就是函数的内存地址
函数名的作用
1.可以被引用
def func():print('func') #打印字符串的内容为func
print(func) #打印变量名func的内存地址
f=func #相当于定义了一个变量,名字是f 值为func
print(f) #打印f的内存地址
f() 调用f
#结果
#<function func at 0x02A94390>
#<function func at 0x02A94390>
#func
12 #func会指向函数的内存地址,不会取用函数里面的值,只有加()才能调用函数
2.可以被当作容器类型(可变数据类型)的元素
1 def func():2 print('func') 3 print(func) 4 f=func 5 print(f) 6 l = [f] 7 print(l) 8 l[0] == f 9 l[0]() 10 11 12 <function func at 0x0000025B3C73B9D8> 13 <function func at 0x0000025B3C73B9D8> 14 [<function func at 0x0000025B3C73B9D8>] 15 func
3.可以当作函数的参数和返回值
1 第一类对象(first-class object)指 2 1.可在运行期创建 3 2.可用作函数参数或返回值 4 3.可存入变量的实体。
总之就记住一句话,就当普通变量用
闭包
闭包的定义
内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
1.闭 内部的函数
2.包 包含了对外部函数作用域中变量的引用
由于有了作用域的关系,我们就不能拿到函数内部的变量和函数了。如果我们就是想拿怎么办呢?返回呀!
我们都知道函数内的变量我们要想在函数外部用,可以直接返回这个变量,那么如果我们想在函数外部调用函数内部的函数呢?
是不是直接就把这个函数的名字返回就好了?
闭包函数最常用的用法
1 def func():2 name = 'eva' 3 def inner(): 4 print(name) 5 return inner 6 7 f = func() 8 f()
判断闭包函数的方法.__closure__
输出结果含有cell说明该函数是闭包函数1 def func():
2 name = 'Eden' 3 def inner(): 4 print(name) 5 print(inner.__closure__) 6 return inner() 7 func() #看输出是否有cell元素有就是闭包函数 8 9 10 (<cell at 0x000002711EE465B8: str object at 0x000002711EEDA500>,) 11 Eden 12 16 #输出的__closure__为None :不是闭包函数 17 name = '山鹰' 18 def func2(): 19 def inner(): 20 print(name) 21 print(inner.__closure__) 22 return inner 23 24 f2 = func2() 25 f2() 26 28 None 29 山鹰
闭包函数的嵌套
1 def wrapper():2 money = 1000 3 def func(): 4 name = 'Eden' 5 def inner(): 6 print(name,money) 7 return inner 8 return func 9 10 f = wrapper() 11 i = f() 12 i()
闭包函数在网络上的应用
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)
小结:
命名空间: 有三种命名空间从大到小的范围顺序:内置命名空间、全局命名空间、局部命名空间 作用域(包括函数的作用域链): 调用时,如果在自己的空间内有,就用自己的。如果没有就使用大范围的。不能从大范围中用小范围的。 函数的嵌套: 嵌套调用 嵌套定义:定义在内部的函数无法直接在全局被调用 函数名的本质: 就是一个变量,保存了函数所在的内存地址 闭包(必须理解掌握,闭包是为后面装饰器的出现打基础): 内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
相关文章推荐
- 洗礼灵魂,修炼python(23)--自定义函数(4)—闭包进阶问题—>报错UnboundLocalError: local variable 'x' referenced before assign
- python进阶5:外层函数、内层函数和闭包
- python进阶三_函数
- 苹果新的编程语言 Swift 语言进阶(六)--函数和闭包
- Python进阶(二十四)-Python中函数的参数定义和可变参数
- 学习笔记-小甲鱼Python3学习第二十讲:函数:内嵌函数和闭包
- Python进阶笔记(2)_ 函数式编程 之 闭包和装饰器decorator
- <Python进阶读书笔记>之(一) 函数不定参数传递
- python_fullstack基础(六)-函数进阶
- Python进阶07 函数对象
- 2.Python进阶-Python语句结构+Python函数应用
- 我与python约个会:13编程进阶~函数
- Python进阶---python strip() split()函数实战
- Python进阶---python strip() split()函数实战(转)
- Python进阶07 函数对象
- 苹果新的编程语言 Swift 语言进阶(六)--函数和闭包
- python进阶教程之函数对象(函数也是对象)
- python进阶教程之函数对象(函数也是对象)
- Python函数中的函数(闭包)用法实例
- python学习返回函数(闭包)