函数对象、函数的嵌套调用与定义、名称空间、作用域、闭包函数
昨日补充内容:
定义函数的三种方式:
1.空函数:可以快速的帮助自己构建项目框架,使项目架构清晰明了
def func(): pass
这种方式应用频率非常高
比如购物车功能:
def register(): pass def login(): pass def pay(): pass
2.无参函数:
def func(): print('from func')
3.有参函数:
def func(x,y,*args,**kwargs) print(x,y,*args,**kwargs)
命名关键字参数:在函数定义阶段,写在*与** 可变长参数之间的形参
特点:
- 1.在给命名关键字参数传值的时候,只能用关键字为其传值
- 2.在定义阶段,给人的感觉好像是z是默认值参数,放在了m这个位置参数之前,且应该报错,其实z和m都是命名关键字参数,而不是默认值参数和位置参数
def func(x,y=1,*args,z=3,m,**kwargs) print(x,y) # 1 2 print(args) # (3,4,5,6,7,8) print(z,m) # z=88,m=99 print(kwargs) # {'0':11,'s':22} func(1,2,3,4,5,6,7,8,z=88,m=99,o=11,s=22)
函数对象
函数是第一类对象:函数名指向的值可以被当作参数传递
特点:
1.函数名可以被传递
name = 'jason' x = name print(x) # 'jason' def func(): print('from func') print(func) f = func func() print(f) f() # f其实指向的也是 函数func指向的 函数体代码的内存地址
2.函数名可以被当作参数传递给其他函数
def func(): print('from func')
def index(args): print(args) args() print('from index') index(1) index(func)
3.函数名可以被当作函数的返回值
def index(): print('from index') def func(): print('from func') 若return 11 res = func() print(res) # 结果为 11 res() 若return index res1 = func() print(res1) # <function index at 内存地址> res1()
4.函数名可以被当作容器类型的参数
def func(); print('func') # <function func at 内存地址> print(func()) # None l = [1,2,func,func()] print(l) # [1,2,<function func at 内存地址>,None]
ATM+购物车项目
需求:循环打印项目功能,供用户选择,用户选择谁就执行谁
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...') msg = '''''' 1 注册 2 登陆 3 转账 4 购物 5 支付 '''''' func_dict = { '1':register, '2':login, '3':transfer, '4':shopping, '5':pay } while True: print(msg) choice = input('请选择你想要执行的功能>>>:').strip() if choice in func_dict: func_dict.get(choice)() '''等价于函数名()''' else: print('功能暂时没有')
函数的嵌套调用
在函数内部调用其它函数
def index(): print('index') def func(): index() print('func') func() # 结果为 index func
def index(): func() print('index') def func(): print('func') index() # 结果为 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) # 返回值为a,b中大的值 res2 = my_max(res1,c) res3 = my_max(res2,d) return res3 print(my_max4(1,2,10,4)) # 结果为10
函数的嵌套定义(重要)
def outer(): x = 1 print('outer') def inner(): print('inner') print(x) # 报错 print(inner) # 报错 outer() # 结果为outer
def outer(): x = 1 print('outer') def inner(): print('inner') print(inner) # <function inner at 内存地址> inner()
def outer(): x = 1 print('outer') # 结果为outer def inner(): print('inner') return inner res = outer() print(res) # <function outerr.<locals>.inner at 内存地址> res() # 结果为inner
函数的嵌套定义及应用场景
'''
写一个函数
该函数用户可以通过传参的不同来控制函数执行不同的代码
'''
def all_func(type): def register(): print('register') def login(): print('login') def pay(): print('pay') if type == '1': register() elif type == '2': login() elif type == '3': pay() all_func('1') all_func('2') all_func('3')
名称空间是什么?(重要)
名称空间就是放名字的地方
详细解释:存放的是变量名与变量值的内存地址的绑定关系的地方
要想访问一个变量的值,就必须先去名称空间中拿到对应的名字,才能够访问变量的值
名称空间的分类:
- 1.内置名称空间:python解释器提前给你定义好的名字(事先已经存放到内置名称空间中了);比如(len、max、min等)
- 2.全局名称空间:文件级别的代码,具体如下
x = 1 if l == 1: y = 2 print(y) while True: z = 3 for i in [1,2,3]: print(i)
如上代码中x,y,z都会放到全局名称空间,if、while、for无论嵌套多少层,它们内部所创建的名字都是全局名称空间的
- 3.局部名称空间:函数体内创建的名字都属于局部名称空间
名称空间的生命周期:
- 内置名称空间:只要python解释器一启动就立马创建;关闭python解释器时,就自动销毁
- 全局名称空间:只要你右键运行py文件,会自动创建,py文件运行结束时自动销毁
- 局部名称空间:函数被调用时自动创建,函数执行结束后立即销毁(动态创建、动态销毁)
名称空间的查找顺序(重要):
1.需要先确定你当前在哪(大前提)
- 1):站在全局:全局>>>内置
- 2):站在局部:局部>>>全局>>>内置
2.例题
函数在定义阶段查找名字的顺序就已经固定了,不会因为函数的调用位置变化而改变
len = '我是全局名称空间的len' def func(): len = '我是局部名称空间的len' print(len) print(len) # 这里是在全局
def func(): len = '我是局部名称空间的len' print(len) print(len) # 这里是内置len, built-in function len
len = '我是全局名称空间的len' def func(): len = '我是局部名称空间的len' print(len) func() # 这里是局部名称空间的len
len = '我是全局名称空间的len' def func(): print(len) func() # 这里是全局名称空间
作用域
全局作用域:
- 全局有效:内置名称空间,全局名称空间
局部作用域:
- 局部有效:局部名称空间
global、nonlocal
1.global在局部修改全局的变量
x =1 def func(): x = 2 func() print(x) # 结果为1
x = [] # 因为列表是可变类型,所以能够从局部修改全局 def func(): x.append('嘿嘿嘿') func() print(x)
# global 可以在局部修改全局的不可变数据类型 x = 1 def func(): global x # 修改全局变量,而不是创建局部名称空间 x = 2 func() print(x) # 结果为2
2.nonlocal 局部修改局部
def func(): x = 1 def index(): x = 2 print(x) func() # 结果为1
def func(): x = 1 def index(): nonlocal x x = 2 print(x) func() # 结果为2
'''
global:局部修改全局,如果想修改多个,逗号隔开
nonlocal:局部修改局部,如果想修改多个,逗号隔开