1 函数定义的三种方式
1空函数
2无参函数
有参函数
2 命名关键字传参
在函数定义的期间,放在*args与**kwasgs之间的参数叫做命名关键字传参
def func(x,y=1,*args,z=3,m,**kwargs): #感觉z默认参数,m是位置参数,z放在了m的前面,其实他们都是命名关键字参数 print(x,y) print(args) print(z,m) print(kwargs) func(1,2,1,2,3,4,5,6,7,78,8,9,0,z=69,m=999,o=666999,l = 999666)
3 函数对象
函数是第一类对象,函数名指向的值是可以当做参数传递的
第一种情况;函数名被变量传递
name = 'jason' x = name print(name,id(name)) print(x,id(x)) def func(): print('from func') print(func) print(id(func)) f = func print(f) print(id(f)) func() f() # 其实此时的f也是指向的是func的函数代码体的内存地址,所以f加括号可以调用函数
第二种情况;函数名可以当做实参,传递给其他函数
def index(): print("index") def func(args): print("func") args() func(index) # 注意,如果你传入的函数名定义在调用函数的下面 #会报错
第三种情况;函数名可以当做函数的返回值
def func(): print("func") def index(): print("index") return func ret = index() # 注意此时index()这个函数已经被调用,返回值就是上一个函数的函数名 ret() # 拿到这个返回值就可以调用func的这个函数
第四种情况;可以当做容器类型的参数
下面两种代码风格的不同,导致了代码的行数加多
第一种如果每一次加入了一项功能,就要再多写一个函数
并且,还要多谢写一个控制语句,很麻烦
但第二种我们就不需要写控制语句
我们只需要将函数与用户想要输入的对应起来,将函数的
函数名一一对应加入到列表中去就可以了
如果下一吃还要加功能,那就只需要加一个函数,然后在将字典中加入一个
函数对应的字符就可以了
def func(): print("func") def index(): print("index") def info(): print("info") while True: choose = input("请输入你想要的功能") if choose == "1": func() elif choose == "2": index() elif choose == "3" info() else: print("你输入的功能还没有开发,敬请期待")
def func(): print("func") def index(): print("index") def info(): print("info") msg = {"1":func,"2":index,"3":info} while True: choose = input("请输入你想要的功能") if choose in msg: msg.get(choose)() else: print("你输入的功能还没有开发,敬请期待")
4 函数的调用嵌套
函数内部调用其它函数可以将复杂的逻辑简单化
基本格式
def func(): print("func") def index(): print("index") func() index()
比较4个数字的大小
def my_max2(x,y): if x > y: return x return y def my_max4(a,b,c,d): res1 = my_max2(a,b) # 注意此时的 a,b 是变量 在调用my_max4的时候回赋值给他,它会继续赋值给他的函数体x,y res2 = my_max2(res1,c) res3 = my_max2(res2,d) return res3 a = my_max4(1,22,88,44) print(a)
5 函数嵌套定义
注意,如果info这个函数在调用函数的下方,会报错。错误是没有定义就使用了
def info(): print("info") def func(): print("func") def index(): print("index") return info return index ret = func() a = ret() a()
6 名称空间
就是存放变量名与变量值地址绑定关系的的空间
想访问一个变量值,就必须到名称空间找到变量地址对应的变量名字
名称空间分为3种
第一种;内置名称空间
就是Python解释器提前给你定义好的名字
第二种;全局名称空间
文件级别的代码 if while for无论循环多少层都是全局名称空间的
第三种;局部名称空间
函数体内定义的创建出来的名字都是局部变量
生命周期
内置名称空间,当Python解释器运行就会自动创建,关闭Python解释器就UI自动销毁
全局名称空间,当Python文件运行就会自动创建,关闭文件就会自动销毁
局部名称空间,当创建函数是就会自动创建,函数结束时就会自动销毁
7 名称空间查找顺序
查找顺序(需要确定你现在站在哪里****)
1 站在全局;全局>>>内置
2 站在局部;局部>>>全局>>>内置
记忆方法;(自下而上)
例1
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() # x = 888 f2() # x = 999 x = 1221212 f1() # x =88888
解析;
如果 x 在函数f4里面,(这里的里面就是指在函数定义和函数调用之间)我们的x是能答应出来的
如果是x没在函数f4里面他就会去他的上一层函数去找,如果有就会答应x的值,如果有多个就就会打印最后的一个的值
如果在在f4调用函数的下面就会报错。没有定义的变量
例2
def func(): # x = 1 def index(): print(x) # 获取全局找x return index res = func() # x = 999 res() # x = 999
解析;
第一步,判断x是否在函数index中,如果没有就会去上一层函数中找
如果还是没有就继续上一层中找
在上一层就是全局名称空间
如果有就打印,如果么有就会报错
例3
x=111 def outer(): def inner(): print('from inner',x) return inner f=outer() x = 222 f()
解析
x先是在自己函数中找,没有,就到了上一层找
上一层也没有,就到了全局名称空间找
然后x=111,到x=222取到的是222
例4
x=111 def outer(): def inner(): print('from inner',x) return inner f=outer() def func(): x=333 f() func()
解析
x先是在自己函数中找,没有,就到了上一层找
上一层也没有,就到了全局名称空间找
然后x=111,取到111,他不会去下一个函数找,遵循,局部名称空间>>>到全局空间 名称空间>>>到内置空名称空间
列5
x=111 def outer(): def inner(): # x = 888888 print('from inner',x) x = 66666666 return inner f=outer() f()
解析;
此时的x会报错
变量必须先定义,在使用
终极x的位置分析
# x = 700 def func(): # x = 100 def index(): # x = 200 def info(): # x = 300 print(x) # x = 800 # x = 400 info() # x = 900 # x = 500 index() # x = 1000 # x = 600 func() x = 100
8 作用域
global 和 nonlocal
global 在局部修改全局的不可变类型数据
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()