哪个更痛苦,努力还是后悔?
前方高能---函数的进阶
1.函数参数--动态传参
2.名称空间,局部名称空间,全局名称空间,作用域,加载顺序
3.函数的嵌套
4.gloabal,nonlocal关键字
一. 函数参数--动态传参
形参的第三种: 动态参数
1. 动态接收位置参数
动态接收参数的时候要注意: 动态参数必须在位置参数后面.
def chi(*food, a, b): print('我要吃,',food,a,b) chi('大米饭','小米饭',a='黄瓜',b='茄子') # 必须用关键字参数来指定.
先写位置函数,然后再用动态函数.
def chi(a,b,*food): print('我要吃',a,b,food) chi('大米饭','小米饭','啦啦啦','面条') # 前两个参数用位置参数来接收,后面的参数用动态参数接收
顺序: 位置参数,动态参数*,默认值参数.
2. 动态接收关键字参数
在python中可以动态的位置参数,但是'这种情况只能接收位置参数无法接收关键字参数'
在python中使用**来接收动态关键字参数.
def func(**kwagrs): print(kwargs) func(a=1,b=2,c=3) func(a=1,b=2) #结果 {'a':1,'b':2,'c':3} {'a':1,'b':2} # 这个时候接收的是一个dict
顺序的问题,在函数调用的时候,如果先给出关键字参数,则整个参数列表会报错.
def func(a,b,c,d): print(a,b,c,d) # 关键字参数必须在位置参数后面,否则参数会混乱. func(1,2,c=3,4)
所以关键字参数必须在位置参数后面,由于实参是这个顺序,所有形参接收的时候也hi这个顺序,也就是说位置参数必须在关键字参数后面,动态接收关键字参数也在后面.
最后顺序(*):
位置参数,*args,默认值参数,**kwargs
# 如果想接收所有的参数 def func(*args,**kwargs): print(agrs,kwargs) func('麻花藤','马芸',wtf='胡辣汤')
动态参数的另一种传参方式:
def fun(*args): print(args) lst = [1,4,7] fun(lst[0],lst[1],lst[2]) fun(*lst) #可以使用*把一个列表按顺序打散 s = '臣妾做不到' fun(*s) # 字符串也可以打散.(可迭代对象.)
在实参位置上给一个序列, 列表,可迭代对象前面加个* 表示把这个序列按顺序打散.
在形参的位置上的* 表示把接收到的参数组合成一个元组
如果是一个字典,那么也可以打散,不过需要用两个*
def fun(**kwargs): print(kwargs) dic = {'a':1,'b':2} fun(**dic)
函数的注释:
def chi(food,drink): ''' 这里是函数的注释,先写一下当前这个函数是干什么的,比如我这个函数就是一个吃. :param food: 参数food是什么意思. :param drink: 参数drink是什么意思. :return: 返回的是什么东东 ''' print(food,drink) return 'very good'
二 . 命名空间
def fun(): a =10 print(a) fun() print(a) # a不存在了已经.
我们给存放名字和值的关系的空间起一个名字叫:命名空间. 我们的变量在存储的时候就是存储在这片空间中的.
命名空间分类:
1, 全局命名空间--> 我们直接在py文件中,函数外声明的变量都属于全局命名空间
2, 局部命名空间--> 在函数中声明的变量会放在局部命名空间.
3, 内置命名空间--> 存放python解释器为我们提供的名字,list,tuple,str,int这些都是内置命名空间.
加载顺序:
1, 内置命名空间
2,全局命名空间
3,局部命名空间(函数被执行的时候)
取值顺序:
1,局部命名空间
2,全局命名空间
3,内置命名空间
a = 10 def func(): a = 20 print(a) func() # 20
作用域:作用域就是作用范围,按照生效范围来看分为 全局作用域和局部作用域
全局作用域: 包含内置命名空间和全局命名空间,在整个文件的任何位置都可以使用(遵循从上到下逐步执行).
局部作用域: 在函数内部可以使用.
作用域命名空间:
1,全局作用域 : 全局命名空间 + 内置命名空间
2, 局部作用域: 局部命名空间
我们可以通过globals()函数来查看全局作用域中的内容,也可以通过locals()来查看局部作用域中的变量和函数信息.
a = 10 def func(): a = 40 b = 20 def abc(): print('哈哈') print(a , b) # 这里使用的是局部作用域 print(globals()) # 打印全局作用域中的内容 print(locals()) # 打印局部作用域中的内容 func()
三. 函数的嵌套
1.只要遇见了()就是函数的调用,如果没有()就不是函数的调用.
2. 函数的执行顺序
def fun1(): print(111) def fun2(): print(222) fun1() fun2() print(111) # 函数的嵌套 def fun2(): print(222) def fun3(): print(666) print(444) fun3() print(888) print(333) fun2() print(555)
四. 关键字global和nonlocal
首先我们写这样一个代码,首先在全局声明一个变量,然后再局部调用这个变量,并改变这个变量的值.
a = 100 def func(): global a # 加了个global表示不再局部创建这个变量了,而是直接使用全局的a a = 28 print(a) func() print(a)
global表示,不再使用局部作用域中的内容了,而改用全局作用域中的变量.
lst = ['哈哈','请问','旺旺'] def func(): lst.append('哎哎啊') # 对于可变数据类型可以直接进行访问,但是不能改地地址,说白了,不能赋值. print(lst) func() print(lst)
nonlocal 表示在局部作用域中,调用父级命名空间中的变量.
a = 10 def func1(): a = 20 def func2(): nonlocal a a = 30 print(a) func2() print(a) func1()