函数对象
函数是第一类对象:即函数可以被当做数据处理。
def func():
print('from func')
print(func)
<function func at 0x00B46858>
一、函数对象的四大功能
1、函数名可以被引用
def func():
print('from func')
f = func # 函数名被引用
f() # from func
2、函数名可以被当做参数传递给其他函数
def func():
print('from func')
def deco(args):
print(args) # <function func at 0x00D66858>
args() # from func
print('from index') # from index
deco(func) # 当做参数传递
3、函数名可以当做其他函数的返回值
def deco():
print('from deco')
def func():
print('func')
return deco
res = func() # func
print(res) # <function deco at 0x00CF6858>
res() # from deco
4、函数名可以当做容器类型的元素
def func():
print('from func')
print(func()) # None
l = [1,2,func,func()]
print(l) # [1, 2, <function func at 0x01776858>, None]
def register():
username = input('username>>>:').strip()
pwd = input('password>>>>:').strip()
print(username,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:
print(func_msg)
choice = input('请选择你想要的功能').strip()
if choice == 'q':
break
func = func_dict.get(choice)
if func:
func()
else:
print('你想要的功能暂时没有')
函数的嵌套调用
函数的调用
在函数内部调用其他函数,是为了使用函数的功能,将复杂的逻辑简单化。
def index():
func()
print('index')
def func():
print('func')
index()
def my_max(x,y):
if x > y:
return x
return y
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,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_func(number):
def register():
print('register')
def login():
print('login')
def transfer():
print('shopping')
func_dict = {
0:register,
1:login,
2:transfer,
}
fun_choice = func_dict.get(choice)
fun_choice()
while True:
print(f'请选择{func_msg}')
choice = int(input('请输入你的选择?>>>>').strip())
all_func(choice)
名称空间与作用域
函数内部的函数只能在函数内部调用,不能在函数外部调用。
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
print(y)
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
print(x)
# 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():
print(x) # 函数定义阶段,x=1,就已经被固定了。
def f2():
x = 10
f1() # 所以函数无论被如何调用,都是一个整体
f2()
global、nonlocal关键字
global在局部修改全局的变量、修改的是不可变数据类型。可变数据类型会自动修改,不要用global。
# 可变数据类型可直接在局部修改全局的变量
x = []
def func():
x.append('嘿嘿嘿')
func()
print(x) # ['嘿嘿嘿']
# global 修改局部变量为全局变量
x = 1
username = 'jason'
def func():
global x,username # 将局部变量x,username的值999,'egon',修改为全局变量x,username的值
x = 999
username = 'egon'
func()
print(x) # x = 999
print(username) # username = 'egon'
# nonlocal 修改局部变量为局部变量
def func():
x = 1
def index():
nonlocal x # 将局部变量index函数内部的x的值2,修改为局部变量fun函数的x的值
x =2
index()
print(x)
func()
global:局部修改全局,如果想修改多个,用逗号隔开
nonlocal:局部修改局部,如果想修改多个,用逗号隔开