一.函数是第一类对象,即函数可以当作数据传递
1.可以被引用
2.可以当作参数传递
3.返回值可以是函数
4.可以当作容器类型的元素
def foo():
print('foo')
def bar():
print('bar')
dic = {
'foo':foo,
'bar':bar,
}
while True:
choice = input('输入:').strip()
if choice in dic:
dic[choice]()
二.函数嵌套
1.函数的嵌套调用 (调用函数必须有返回值)
def max(x,y):
return x if x > y else y
def max4(a,b,c,d):
res1 = max(a,b)
res2 = max(res1,c)
res3 = max(res2,d)
return res3
print(max4(1,2,3,4))
2.函数的嵌套定义
def f1():
def f2():
def f3():
print('from f3')
f3()
f2()
f1()
f3() '''遵循先定义后引用,执行函数的过程是,
先将函数作为文本文件加载到内存,但是
在调用之前函数内的代码都是普通的文本
无语法意义,所以在此处调用f3()会报错,
因为f3()还没有被定义
'''
三.名称空间与作用域
一.什么是名称空间?
名称空间:存放名字的地方,三种名称空间(之前遗留的问题x = 1, 1存放于内存中,那么名字x存放在南里呢?
名称空间正是存放名字x与1绑定关系的地方)
二.名称空间的加载顺序
python test.py
1.python解释器先启动,因而首先加载的是:内置名称空间
2.执行test.py文件,当然以文件为基础,加载全局名称空间
3.在执行文件的过程中如果调用函数,则临时产生局部名称空间
三.名字的查找顺序
需要注意的是:在全局无法查看局部的,在局部可以查看全局的
# max = 1
def f1():
# max = 2
def f2():
# max =3
print(max)
f2()
f1()
print(max)
四.作用域
1.作用域即范围
-全局范围(内置名称空间与全局名称空间属于该范围): 全局存活,全局有效
-局部范围(局部名称空间属于该范围):临时存活,局部有效
2.作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
x = 1
def f1():
def f2():
print(x)
return f2
# x = 100
def f3(func):
x = 2
func()
x = 10000
f3(f1())
'''
在这里调用函数,即把def f3()这段代码块放在了这里运行
在func()的位置传入了由f1()得到的f2的返回值,加括号运行
x在函数内找不到x就会去外层找,找不到就一直推到全局,
x = 10000覆盖了之前的定义,所以结果是10000,
x = 2是定义在f3的局部作用域里,所以在f2里是不能找到
x = 2的
'''
五.global与nonlocal关键字
申明作用域
四.闭包函数
一.什么是闭包函数
内部函数包含对外部作用域而非全局作用域的引用
首先闭值的是封闭修改,包则指的是包含外部作用域的引用
例:
def outter():
x = 1
def inner():
print(x)
return inner
f1 = outter()
x = 110
f1()
def counter(): # 定义一个包函数
n=0 # 定义在外部的值
def incr(): # 定义一个闭函数
nonlocal n # 申明作用域
x=n # 定义x = n
n+=1 # n += 1
return x # 得到x的返回值
return incr # 得到incr的返回值,即函数体运行的过程,加()可以调用
c=counter() # 这里定义的c,相当于定义c 等于函数counter()运行
print(c()) # 的结果,即incr的返回值
print(c()) # 加括号调用
print(c())
print(c.__closure__[0].cell_contents) #查看闭包的元素
二.闭包的意义与应用
1.返回函数对象,不仅仅是一个函数对象,在该海曙外还包裹了一层作用域,这使得,该函数
无论在何处被调用,优先使用自己外层包裹的作用域