今日内容
-
函数对象
-
函数嵌套
-
名称空间与作用域
-
闭包函数
# 函数是第一类对象: 指的是函数名指向的值(函数)可以被当作数据去使用
def func(): # func=函数的内存地址
print('from func')
# print(func)
age=10
# 1. 可以被引用
x=age
print(x,age)
f=func
print(f)
f()
# 2. 可以当作参数传给另外一个函数
def bar(x):
print(x)
bar(age)
bar(func)
# 3. 可以当作一个函数的返回值
def bar(x):
# return x
res=bar(age)
print(res)
res=bar(func)
print(res)
# 4. 可以当作容器类型的元素
# l=[age,func,func()]
# print(l)
def login():
print('login')
def register():
print('register')
def shopping():
print('shopping')
def pay():
print('pay')
def transfer():
print('transfer')
func_dic={
'1':login,
'2':register,
'3':shopping,
'4':pay,
'5':transfer
}
# print(func_dic)
msg="""
0 退出
1 登陆
2 注册
3 购物
4 支付
5 转账
"""
while True:
print(msg)
choice=input('请输入您的操作: ').strip()
if choice == '0':break
# if choice == '1':
# login()
# elif choice == '2':
# register()
# elif choice == '3':
# shopping()
# elif choice == '4':
# pay()
# else:
# print('输入错误指令,请重新输入')
if choice in func_dic:
func_dic[choice]()
else:
print('输入错误指令,请重新输入')
def f1():
print('from f1')
def f2():
print('from f2')
f1()
# 函数嵌套调用应用场景
def my_max(x,y):
if x > y:
return x
return y
def max4(a,b,c,d)
res1 = my_max(a,b)
res2 = my_max(res1,c)
res3 = my_max(re2,d)
return res3
print(max4(1,2,3,4)) # 这样函数嵌套的好处在于讲复杂的问题拆分
"""
函数的嵌套定义
"""
# 函数的嵌套定义:函数内定义新的函数
def outter():
print('outter')
def inner():
print('inner')
print(inner)
inner()
# 外部无法直接访问到函数内部的值,要想访问必须在内部同级别访问
# 函数的嵌套定义的应用场景
def all_func(type):
def login():
print('login')
def register():
print('register')
def shopping():
print('shopping')
if type = '0':
login()
elif type = '1':
register()
elif type = '2':
shopping()
'''
1 什么是名称空间namespace
名称空间就是用来存放名字与值内存地址绑定关系的地方(内存空间)
age=18
但凡查找值一定要通过名字,访问名字必需去查找名称空间
ps:小知识点补充:import this查看python之禅
2 名称空间分为三大类
内置名称空间:存放的是python解释器自带的名字
例如:
len
max
print
全局名称空间:存放的是文件级别的名字
例如:以下名字中x\y\z\b\foo都会存放于全局名称空间中
x=1
y=2
if x == 1:
z=3
while True:
b=4
break
def foo():
m=3
局部名称空间:在函数内定义的名字
例如:
foo内的m这个名字一定是存放于一个局部名称空间中
生命周期:
内置名称空间:在解释器启动时则生效,解释器关闭则失效
全局名称空间:在解释器解释执行python文件时则生效,文件执行完毕后则失效
局部名称空间:只在调用函数时临时产生该函数的局部名称空间,改函数调用完毕则失效
加载顺序:
内置->全局->局部
'''
# 案列一:研究名字的查找顺序
len = '我是全局的len'
def foo():
len='我是局部的len'
print('站在局部找len:',len)
foo()
print('站在全局找len: ',len)
"""
名字查找规律:
假设当前站在局部,查找顺序:局部->全局->内置
假设当前站在全局,查找顺序:全局->内置
"""
# 案例二:多层函数嵌套 画图演示层级关系
x = 111
def f1():
x = 222
def f2():
x = 333
def f3():
x = 444
print(x)
# x = 333 # 将x=333换到这里,诠释查找名字并不是简单的从“头顶上“找
f3()
f2()
f1()
"""
名字的查找顺序,在函数定义阶段就已经固定死了(即在检测语法时就已经确定了名字的查找顺序),与函数的调用位置无关,也就是说无论在任何地方调用函数,都必须回到当初定义函数的位置去确定名字的查找关系(******)
"""
# 案例:
x=111
def outer():
def inner():
print('from inner',x) # x访问的是全局名称空间中x
return inner
f=outer()
# 下面的注释诠释完成后 加一行代码验证
# x = 222
f() # 打破层级限制,全局访问局部名称空间的名字
# 案列三:
x=111
def outer():
def inner():
print('from inner',x) # x访问的是全局名称空间中x
return inner
f=outer()
def func():
x=333
f()
func()
# 稍微迷惑人的例子
x=111
def outer():
def inner():
print('from inner',x) # x访问的是局部名称空间中x 也就意味着在调用的时候只会在当前局部名称空间中找x,但是x还没有被定义出来
x = 66666666 # 这仅仅是教学演示知识点故意写出来的错误写法
return inner
f=outer()
f()
"""
域指的是范围,作用域指的就是作用的范围,分为两种
全局作用域:包含的是内置名称空间与全局名称空间中的名字
特点:全局有效,全局存活
局部作用域:包含的是局部名称空间中的名字
特点:局部有效,临时存活
"""
# global nonlocal
x=1
def foo():
x=2 # 不可变,局部新建的
foo()
print(x)
l=[]
def foo():
l.append(1) # 可变类型,局部可以直接引用全局
foo()
print(l)
#global:在局部声明一个名字是来自于全局作用域的,可以用来在局部修改全局的不可变类型
x=1
def foo():
global x
x=2
foo()
print(x)
#nonlocal:声明一个名字是来自于当前层外一层作用域的,可以用来在局部修改外层函数的不可变类型
x=0
def f1():
x=111
def f2():
nonlocal x
x=222
f2()
print(x)
f1()