关键字
- 引子
- 命名空间和作用域
- 函数嵌套及作用域链
- 函数名本质
- 闭包
引子
写函数,取三个数中的最大值,并打印 / 理解return的含义 / 进而命名空间及其规则
# 计算三个值中的最大值 def max(a, b): m = a if a > b else b return m def t_max(x, y, z): c = max(x, y) return max(c, z) print(t_max(1,2,3))
# 报错 def max(a, b): m = a if a > b else b max(2, 3) print(m)
运行代码碰到函数时,python编译器只是把函数名放入内存中,并不关心其内在变量和逻辑关系;等到调用时,才用到其中的变量,并放入内存中;函数用完就清空其中变量,故打印错误。
命名空间
存放名字和数值之间的对应关系
分类
全局命名空间
局部命名空间
内置命名空间
三种命名空间的加载顺序
内置命名空间先于程序加载,全局命名空间从上到下加载,局部命名空间从上到下加载
作用域
即作用范围
全局作用域和局部作用域
def func(): a = 12 b = 20 print(locals()) print(globals()) func()
# global关键字 a = 10 def func(): global a a = 20 print(a) func() print(a)
函数的嵌套和作用域链
嵌套
# in f1 # in f2 # in f3 def f1(): def f2(): def f3(): print("in f3") print("in f2") f3() print("in f1") f2() f1()
注意:内部函数修改不可变外部参数会报错,只可以用,不可以改
def func(): a = 1 def func1(): a += 1 # 不可修改 func1() print(a) func()
作用域链
# a = 1 def f1(): a = 1 def f2(): a = 2 f2() print('a in f1 : ',a) f1()
nonlocal关键字
外部必须有这个变量
内部修改这个变量如果想在外部有这个变量的第一层函数中生效
def f1(): a = 1 def f2(): nonlocal a a = 2 f2() print('a in f1 : ',a) f1()
函数名
本质是内存地址
1. 可被引用
def func(): print('in func') f = func print(f)
2. 可被当作容器类型的元素
def f1(): print('f1') def f2(): print('f2') def f3(): print('f3') l = [f1,f2,f3] d = {'f1':f1,'f2':f2,'f3':f3} #调用 l[0]() d['f2']()
3. 可被当作函数的参数和返回值
第一类对象 : 满足以上三种条件的对象
闭包
内部函数中包含对外部作用域而非全局作用域名字的引用,该内部函数成为闭包函数
通常拿到内部函数的名字,不必每次都建立一个有全局作用域的函数,效率高
def func(): name = 'eva' def inner(): print(name) return inner f = func() f()
判断闭包函数的方法
#输出的__closure__有cell元素 :是闭包函数 def func(): name = 'eva' def inner(): print(name) print(inner.__closure__) return inner f = func() f() #输出的__closure__为None :不是闭包函数 name = 'egon' def func2(): def inner(): print(name) print(inner.__closure__) return inner f2 = func2() f2()
闭包的嵌套
def wrapper(): money = 1000 def func(): name = 'eva' def inner(): print(name,money) return inner return func f = wrapper() i = f() i()
闭包函数获取网络应用
from urllib.request import urlopen def index(): url = "http://www.douban.com" def get(): return urlopen(url).read() return get douban = index() content = douban() print(content)