目 录
函数名称空间和查找顺序练习题(重点:待更新)
一、函数对象
函数对像是第一类对象:函数名所指向的值可以被当做参数进行传递。
1、函数名可以被当做参数进行传递,进行赋值
# 函数对象 def func(): print('函数对象可以被赋值!') func() # f = func # 函数进行赋值的时候一定要是函数名赋值,千万不能加括号,函数名+括号就是函数的调用 f() # 函数对象可以被赋值 -- f其实指向的也就是桉树func指向的函数体代码块的内存地址
2、函数名可以传递给其他函数传参
# 作为其他函数的参数 def func(): print('第一参数') def func2(x): print(x) # <function func at 0x02CC4810> 函数名func指向的函数体的内存地址 func() # 第一参数 print('第二参数') # 第二参数 func2(func)
3、函数名可以作为函数的返回值
# 3.函数名可以被当做函数的返回值 def index(): print('index') def func(): print('func') return index res = func() # 结果res = index print(res) # 打印函数名index所指向的函数体代码块的内存地址 res() # index函数调用
执行书序图解:
4、函数可以作为其他容器类型里面的元素
# 循环打印项目功能提示信息 供用户选择 用户选择谁就执行谁 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': # register() # elif choice == '2': # login() # elif choice == '3': # transfer() # elif choice == '4': # shopping() # elif choice == '5': # pay() else: print('你输入的功能暂时没有')
二、函数的嵌套
函数的嵌套分为嵌套调用和嵌套定义。
1、函数的嵌套调用:顾名思义是在函数体内调用其他函数
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))
2、函数的嵌套定义:在函数内定义函数
应用场景:在一个函数内通过传不同的参数来实现不同的功能。
def outer(): x = 1 print('outer') def inner(): print('inner') # print(inner) return inner res = outer() # outer()首先print('outer'),再将inner赋值给res,即res指向函数名inner指向的函数体代码所在的内存地址 print(res) # 打印inner所指向函数体代码的内存地址 res() # 将inner赋值给res,并调用
程序实行结果如图:
三、函数的名称空间
名称空间:通俗解释就是存放名字的地方。
详细解释:名称空间是存放变量名和变量值的内存地址绑定关系的地方。我们想要访问一个变量,首先要去名称空间找到变量名,才能找到对应的变量值。
名称空间的分类:
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、局部名称空间:函数内部定义的变量名都属于局部名称空间 例如:username
四、名称空间的查找顺序
名字空间的查找顺序(******)
名字查找顺序如下图所示:
首先要确定你当前的位置(大前提)
1、站在全局 全局 》》》 内置
2、站在局部 局部 》》》 全局 》》》 内置
注意:函数在定义阶段名字的查找顺序就已经确定了,不会因为函数调用位置的变化而变化。*******
函数名称空间和查找顺序练习题(重点:待更新)
1、第一个坑点:
# ----第一个错题 def index(): x = 'xxx' def index2(): print(x) y = 666 index() # 执行完该步骤后定义 x = 'xxx' index2() # 报错!NameError: name 'x' is not defined 局部名称空间无法调用另一个局部名称空间的值
2、第二个坑点
x = 111 def f1(): x = 222 def f2(): x = 333 def f3(): x = 444 def f4(): # 到这一步,先定义函数f4 # x = 555 print(x) # 第4步执行 函数f4代码块。此时在函数f4的名称空间内寻找,找到在 第二步已经定义的x并打印出x的值 x = 6969 # 第二步:x赋值6969 f4() # 第三步调用函数f4 f3() f2() f1() # 结果:6969
3、第三个坑点:
x = 111 def f1(): x = 222 def f2(): x = 333 def f3(): # x = 444 def f4(): # x = 555 print(x) f4() # 错误原因:在函数f4开始调用之后,函数体代码开始运行,但是x=6969还没 有执行 x = 6969 f3() f2() f1() # 结果:报错,x在没有定义前就调用了
4、第4个坑点:
def func(): # x = 1 def index(): print(x) # 获取全局找x return index res = func() x = 999 res() # 结果:999
反例:与第三个坑点相同
# 反例 def func(): # x = 1 def index(): print(x) # 获取全局找x return index res = func() res() # 结果:报错,x还没有定义 x = 999
5、第5个坑点:
# 名字查找练习 x = 111 def outer(): def inner(): print("from index",x) return inner f = outer() # 将函数名inner赋值给f,即f=inner x = 222 # x=222覆盖住 x=111 f() # 结果:from index 222
检测题:要深刻理解“函数在定义阶段名字的查找顺序就已经确定了”这句话
# 名字查找练习 x = 111 def outer(): def inner(): print("from index",x) # x的值已经确定在全局找 return inner f = outer() def func(): x = 333 # x 已经确定在全局名称空间中找,所以不会去函数func中去找 f() func() # 结果:from index 111
五、函数作用域
函数作用域分为全局作用域和局部作用域。
全局作用域:全局有效,主要指内置名称空间,全局名称空间。
局部作用域:局部有效,主要指局部名称空间。
两个关键字:global关键字 和nonlocal关键字
""" global:局部修改全局 如果想修改多个 逗号隔开 nonlocal:局部修局部 如果想修改多个 逗号隔开 """
# global 在局部修改全局的不可变数据类型 # x = [] # 因为列表是可变类型 x = 1 # 不可变类型 username = 'jason' def func(): # x.append('嘿嘿嘿') global x,username # 修改全局变量 而不是创建局部名称空间 x = 999 username = 'egon' func() print(x) print(username)
# nonlocal 局部修改局部 def func(): x = 1 def index(): nonlocal x x = 2 index() print(x) func()