函数对象
函数是第一类对象:即函数可以被当做数据处理。
def func):
print'from func')
printfunc)
<function func at 0x00B46858>
一、函数对象的四大功能
1、函数名可以被引用
def func):
print'from func')
f = func # 函数名被引用
f) # from func
2、函数名可以被当做参数传递给其他函数
def func):
print'from func')
def decoargs):
printargs) # <function func at 0x00D66858>
args) # from func
print'from index') # from index
decofunc) # 当做参数传递
3、函数名可以当做其他函数的返回值
def deco):
print'from deco')
def func):
print'func')
return deco
res = func) # func
printres) # <function deco at 0x00CF6858>
res) # from deco
4、函数名可以当做容器类型的元素
def func):
print'from func')
printfunc)) # None
l = [1,2,func,func)]
printl) # [1, 2, <function func at 0x01776858>, None]
def register):
username = input'username>>>:').strip)
pwd = input'password>>>>:').strip)
printusername,pwd)
print'register....')
def login):
print'login...')
def transfer):
print'transfer...')
def shopping):
print'shopping...')
def pay):
print'pay....')
func_msg = """
1 注册
2 登录
3 转账
4 付款
q 退出
"""
func_dict = {
'1':register,
'2':login,
'3':transfer,
'4':pay,
}
while True:
printfunc_msg)
choice = input'请选择你想要的功能').strip)
if choice == 'q':
break
func = func_dict.getchoice)
if func:
func)
else:
print'你想要的功能暂时没有')
函数的嵌套调用
函数的调用
在函数内部调用其他函数,是为了使用函数的功能,将复杂的逻辑简单化。
def index):
func)
print'index')
def func):
print'func')
index)
def my_maxx,y):
if x > y:
return x
return y
def my_max4a,b,c,d):
res1 = my_maxa,b)
res2 = my_maxres1,c)
res3 = my_maxres2,d)
return res3
printmy_max41,6,8,0)) # 8
函数的嵌套
函数的嵌套是为了用户通过一个函数的操作,实现不同的功能。比如ATM自动取款机。
def outer):
x = 1
print'outer')
def inner):
print'inner')
return inner
res = outer) # outer
res) # inner
func_msg = {
0:'注册',
1:'登录',
2:'购物',
}
def all_funcnumber):
def register):
print'register')
def login):
print'login')
def transfer):
print'shopping')
func_dict = {
0:register,
1:login,
2:transfer,
}
fun_choice = func_dict.getchoice)
fun_choice)
while True:
printf'请选择{func_msg}')
choice = intinput'请输入你的选择?>>>>').strip))
all_funcchoice)
名称空间与作用域
函数内部的函数只能在函数内部调用,不能在函数外部调用。
def deco):
def func):
print'from func')
func)
func) # name 'func' is not defined
一、名称空间
简单来说就是存放名字的地方。
名称空间就是存放变量名与变量值的内存地址的绑定关系的地方。
要想访问一个变量的值,必须先去名称空间中拿到对应的名字,才能够访问变量的值
1.1、 内置名称空间
python解释器提前给你定义好的名字(已经存放到内置名称空间中了),如len、print、int
生命周期:只要python解释器启动就会生效,关闭python解释器时失效。
1.2、 全局名称空间
文件级别的代码
x = 1
if 1==1:
y == 2
printy)
while True:
z = 3
x,y,z都会放到全局名称空间,if for while,无论嵌套多少层,它们内部创建的名字都是全局名称空间的。
生命周期:py文件执行时生效,在py文件执行结束后失效。
1.3、局部名称空间
函数体内部创建的名字都属于局部名称空间
生命周期:函数被调用的时候生效,函数运行结束失效。
1.4、程序的执行顺序(加载顺序)
名称空间的执行顺序为:内置——全局——局部
1.5、查找顺序
查找顺序为:从当前的所在位置开始查找,如果当前所在的位置为局部名称空间,则顺序为:局部——全局——内置
x = 111
def f1):
x = 222
def f2):
x = 333
def f3):
# x = 444
def f4):
# x = 555
printx)
# x = 777
f4)
x = 777
f3)
f2)
f1) # free variable 'x' referenced before assignment in enclosing scope
# x先从f4函数内部开始找,发现没有,就到f3函数内部开始找,发现f4里面有一个x = 777,但是要想传递给x,必须得先执行f4)函数,f4函数内部没有x,就会往外部寻找,一直循环,知道报错。(能看到葡萄但是吃不到葡萄)
函数在定义阶段查找名字的顺序已经被固定了,不会因为函数的调用位置变化而改变。
x = 111
def outer):
def inner):
print'from inner',x)
return inner
f = outer)
x = 222
f) # from inner 222
# x的查找顺序,先在inner函数内部开始查找,发现没有,之后在外部开始查找,这个外部是x=222
x = 111
def outer):
def inner):
print'from inner',x)
return inner
f = outer)
def func):
x = 333
f)
func) # from inner 111
# x的查找顺序,就是outer函数和inner函数执行后,x的查找顺序,发现在外部,x=111
x = 111
def outer):
def inner):
print'from inner',x)
x = 666666
return inner
f = outer)
f) # UnboundLocalError: local variable 'x' referenced
# x的查找顺序,先从本身开始查找,发现有x=66666,但是取不到。会提示报错
二、作用域
2.1、全局作用域
全局作用域:全局有效,全局存活,包含内置名称空间和全局名称空间。
2.1、局部作用域
局部作用域:局部有效,临时存储,只包含局部名称空间。
2.3、注意点
作用域关系在函数定义阶段就已经固定死了,与函数的调用无关。
x = 1
def f1):
printx) # 函数定义阶段,x=1,就已经被固定了。
def f2):
x = 10
f1) # 所以函数无论被如何调用,都是一个整体
f2)
global、nonlocal关键字
global在局部修改全局的变量、修改的是不可变数据类型。可变数据类型会自动修改,不要用global。
# 可变数据类型可直接在局部修改全局的变量
x = []
def func):
x.append'嘿嘿嘿')
func)
printx) # ['嘿嘿嘿']
# global 修改局部变量为全局变量
x = 1
username = 'jason'
def func):
global x,username # 将局部变量x,username的值999,'egon',修改为全局变量x,username的值
x = 999
username = 'egon'
func)
printx) # x = 999
printusername) # username = 'egon'
# nonlocal 修改局部变量为局部变量
def func):
x = 1
def index):
nonlocal x # 将局部变量index函数内部的x的值2,修改为局部变量fun函数的x的值
x =2
index)
printx)
func)
global:局部修改全局,如果想修改多个,用逗号隔开
nonlocal:局部修改局部,如果想修改多个,用逗号隔开
Never,Never,Never give up.