一、函数对象之函数名
1.1 函数名传递
#函数名可以被传递 #函数返回值是返回给函数func(),带括号的 ,print(func())会输出返回值None,当然也会调用一次函数 #func 不带括号,是函数名,打印会输出一个地址,地址加()就会再次调用一次函数 def func(): print('from func') func() # 调用函数,显示from func,这个是print输出的结果 并不是函数的返回值 print(func()) # from func 和 None 相当于调用一次函数打印一次from fun 又输出一次函数返回值None print(func) #<function func at 0x0000000001CF2E18> 不带括号是函数名,代表内存地址 f = func print(f) #<function func at 0x0000000001CF2E18> f() # from func 加括号相当于func(),那么就会调用一次函数
1.2 函数名可以被当做参数传递给其他函数
def func(): print('from func') def index(args): print(args) args() #相当于func(),函数优先级最高,不在往下执行,直接跳到函数开始执行,执行完毕才开始打印下面的from index print('from index') index(func) <function func at 0x0000000002052E18> from func from index
![](https://i-blog.csdnimg.cn/blog_migrate/6818b5d3b36b78c0ccf86701cbb6b164.png)
1.3函数名可以被当做函数的返回值
ef index(): print('index') def func(): print('func') #func return index #即 func()= index ,那么func()()=res()=index()=调用函数 res = func() print(res) #<function index at 0x0000000002032E18> 相当于输出函数返回值 res() #index 相当于index() 开始调用函数 func <function index at 0x00000000001D2E18> index
1.4 函数名,返回值,可以被当做容器类型的参数
def func(): print('func') print(func()) #func None 函数优先级最高,首先会调起函数,运行完再打印返回值 l = [1,2,func,func()] #func 遇到函数必定会执行 print(l) # [1,2,<function func at 0x000001F7D79899D8>,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 ...') 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)() # 相当于 函数名() 可立即调用函数 # if choice == '1': #第三步通常想法,但是这样太长了,可以定义一个字典,key为商品编号,value为函数名,输入编号就会调用相应函数模块 # register() # elif choice == '2': # login() # elif choice == '3': # transfer() # elif choice == '4': # shopping() # elif choice == '5': # pay() else: print('你输入的功能暂时没有')
二、函数嵌套调用
1.在函数内部调用其他函数,可以将复杂的逻辑简单化 #比较a b c d 最大值 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,2,10,4)) #10
2.写一个函数,该函数用户可以通过传参的不同,控制函数执行不同的功能
def all_faction(type): def register(): print('register ...') def login(): print('login ...') if type == 1: #定义规则 register() if type == 2: login() all_faction(1) # register ... 用户只需输入相应参数即可调用相应函数
三、名称空间
3.1名称空间分类
1.内置名称空间:python解释器提前给你定义好的名字(已经存放到内置名称空间中了) len max min 2.全局名称空间:文件级别的代码 x = 1 if 1 ==1 : y = 2 print(y) while True: z = 3 x,y,z都会放到全局名称空间 if for while 无论嵌套多少层 它们内部所创建的名字都是全局名称空间的
3.局部名称空间:函数体内创建的名字都属于局部名称空间
3.2名称空间的生命周期
1.内置名称空间:只要python解释器已启动立马创建 关闭python解释器的时候内置名称空间自动销毁 2.全局名称空间:只要你右键运行py文件会自动创建 py文件程序运行结束自动销毁 3.局部名称空间:函数被调用的时候自动创建 函数指向结束立即销毁(动态创建动态销毁)
3.3 名称空间查找顺序
![](https://i-blog.csdnimg.cn/blog_migrate/13f5ae4bc154ed82e1a1102bd475bb20.png)
#站在全局,自己有用自己
len = '我是全局名称空间的len'
def func():
len = '我是局部名称空间的len'
print(len)
print(len) #我是全局名称空间的len
#站在全局,自己没有找内置
def func():
len = '我是局部名称空间的len'
print(len)
print(len) #<built-in function len>
#站在局部,自己有找自己
len = '我是全局名称空间的len'
def func():
len = '我是局部名称空间的len'
print(len) #我是局部名称空间的len
func()
#站在局部,自己没有先找全局
len = '我是全局名称空间的len'
def func():
print(len) #我是全局名称空间的len
func()
#站在局部,自己没有先找全局也没有找内置
def func():
print(len) #<built-in function len>
func()
实例1
#第一种
x = 111 def f1(): x = 222 def f2(): x = 333 def f3(): x = 444 def f4(): # x = 555 print(x) # 777 并不是444 444和777都属于f3 f4里面找不到就找f3的 f3中x被重新赋值为777了,444已经被覆盖不存在了 x = 777 # 纯粹为了教学演示 f4() f3() f2() f1()
#第二种
x = 111
def f1():
x = 222
def f2():
x = 333
def f3():
# x = 444
def f4():
# x = 555
print(x) # 直接报错 f4没有去f3找,f3有x=777但是是在f4运行前定义的,就是有就是不给用,更不能去f2找
f4()
x = 777
f3()
f2()
f1()
函数在定义阶段查找名字的顺序就已经固定了 不会因为函数的调用位置变化而改变(******)
实例2
#第一种
def func(): x = 1 def index(): print(x) # 1 查找顺序固定死了,自己没有就找上一级局部,不会因为调用位置改变查找顺序 return index res = func() x = 999 res()
#第二种 def func(): # x = 1 def index(): print(x) # 999 自己和上一级局部都没有就到全局找,999定义在函数执行前合理,如果x=999放在res()后面就会报错 return index res = func() x = 999 res() 函数在定义阶段查找名字的顺序就已经固定了 不会因为函数的调用位置变化而改变(******)
3.4 名称空间 作用域
1. global:局部修改全局 如果想修改多个 逗号隔开
2. nonlocal:局部修局部 如果想修改多个 逗号隔开 # global 在局部修改全局的不可变数据类型 x = 1 y = 5 username = 'jason' def func(): global x,username # 修改全局变量 而不是创建局部名称空间 x = 999 username = 'egon' y = 10 func() print(x) #999 print(y) #5 站在全局只找全局 print(username) #egon # nonlocal 局部修改局部 def func(): x = 1 def index(): nonlocal x x = 2 index() print(x) #2 func()