函数的动态参数和命名空间还有关键字/嵌套
1,动态参数(形参):顾名思义就是这个参数是时刻在变化的,动态格式: *函数名 =动态参数,列如:(*food)
- 1>位置参数的动态参数:*args()能接收任意的位置参数.
def func(*args): # *args接收所有的位置参数 print("我喜欢:", args) # 我喜欢: ('李智恩', '陈乔恩', '宋慧乔', '吴宣仪') # 此时返回的是一个元组 func("李智恩", "陈乔恩", "宋慧乔", "吴宣仪") def func(*args, a, b): print("我喜欢:", args, a, b) # TypeError: func() missing 2 required keyword-only arguments: 'a' and 'b' # 会 包这样一个错,是因为这是的位置参数都被动态参数接收, # 等到位置参数a,b的时候即郿参数了,函数调用不起来,程序运行失败 func("李智恩", "陈乔恩", "宋慧乔", "吴宣仪") # 动态参数接收数据时那必须放在位置参数的后边
- 默认参数:
def func(a, b, c="李子璇", *args): print("我喜欢:", a, b, c, args) func("李智恩", "陈乔恩", "宋慧乔", "吴宣仪") # # 我喜欢:"李智恩","陈乔恩","宋慧乔",("吴宣仪,") func("李智恩", "陈乔恩") # 我喜欢:"李智恩","陈乔恩","李子璇"()...空的元组,因为没有值给它 func("李智恩", "陈乔恩", "宋慧乔") # 喜欢:"李智恩","陈乔恩","宋慧乔"().....空的元组,同样没有值给它 func("李智恩", "陈乔恩", "宋慧乔", "吴宣仪", "赵丽颖") # 我喜欢:"李智恩","陈乔恩","宋慧乔",("吴宣仪","赵丽颖")
- #由此可见:当默认参数在动态参数前边时,只有一种情况默认值才会产生.
- #....当位置参数>动态参数*>默认参数时,默认值参数始终生效(当给默认值参数关键字参数时,默认参数失效)
2,动态接收关键字参数,用**来接收动态关键字参数.
- 2.1>列如:
def func(**kwargs): print(kwargs) func(a=1, b=2, c=3) # {"a":1,"b":2,"c":3}返回的是一个字典
- 2.2>列如:
def func(a, b, **kwargs): print(a, b, kwargs) func(1,2,c=3) # 1 2 {'c': 3}返回的是一个字典和2个元素 func(1, b=2, 3) # 报错,关键字和位置参数混乱 # SyntaxError: positional argument follows keyword argument func(a=1, b=2, c=3) # 1 2 {'c': 3} # 返回的是一个字典和2个元素
- #顺序是:位置参数>*args>默认值参数>**kwargs
- #*args接收任意的动态位置参数
- #**kwargs接收的是动态关键字参数
- 2.3>list和dict和字符串的传参:调用函数的时候func(*list/*dict/*s(s="帅爆太阳的男人"))...................把相应的list/dict/字符串拍碎放到元组里
def func(*args): print(args) lst = ["帅","爆","太","阳","的","男","人"] dic = {1: "帅", 2: "爆", 3: "太", 4: "阳", 5: "的", 6: "男", 7: "人"} s = "帅爆太阳的男人" func(*lst) # ('帅', '爆', '太', '阳', '的', '男', '人') # 把lst拍碎放到一个新的元组中,实质是把lst中的每一个元素迭代放到元组中 func(*dic) # (1, 2, 3, 4, 5, 6, 7) # 把dic拍碎放到一个新的元组中,实质是把dic中的每一个元素key迭代放到元组中,字典拍碎只有key值 func(*s) # ('帅', '爆', '太', '阳', '的', '男', '人') # 把s字符串拍碎放到一个新的元组中,实质是把字符串中的每一个元素迭代放到元组中 func(*lst, *dic) # ('帅', '爆', '太', '阳', '的', '男', '人', 1, 2, 3, 4, 5, 6, 7) # 把lst中每一个元素和dic中的key值作为元素放到元组中
- 补充:当dic中拍碎就用(**dic)拍出来的是键值对.
3,命名空间:在我们定义函数和值之间的关系时,会开辟一个内存空间,这个空间就叫做命名空间.
- 命名空间的分类:
- 1>全局命名空间-->我们在.py文件中函数外声明的变量都属于全局命名空间--->python中我们自己的定义函数
- 2>局部命名空间-->在函数中声明的变量就放在局部你命名空间--->python中我们自己的定义函数
- 3>内置函数空间-->是python解释器中已有的函数命名--->python的内置函数
- 加载顺序:内置函数空间-->全局命名空间--->局部命名空间(函数调用的时候)
- 取值顺序:局部命名空间-->全局命名空间-->内置命名空间
- 3.1>作用域:顾名思义以就是作用的区域(范围),因此分为全局作用域和局部作用域
- 全局作用域包括:全局命名空间 + 内置函数空间
- 局部作用域包括:局部命名空间
用globals()来打印全局作用域的内容,locals()是用来查看局部作用域中的内容(变量和值之间的关系)
def func(): a =40 b = 20 def abc(): print("哈哈") print(a, b) # 这里使用的是局部作用域 40 20 print(globals()) # 打印全局作用域的内容, # {'__name__': '__main__', '__doc__': None, '__package__': None, # '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001B5D9DF1FD0>, # '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, # '__file__': 'D:/python_学习文件/python学习之路/帅爆太阳的男人/日记/blog_code/blog_demo.py', '__cached__': None, # 'func': <function func at 0x000001B5D9CF3158>} print(locals()) # 打印的是局部作用域的内容 # {'abc': <function func.<locals>.abc at 0x000001B5DA0626A8>, 'b': 20, 'a': 40} func()
4,函数的嵌套:调用函数的时候必须用()如果不写那就不调用,在嵌套中最重要的是看调用时那个函数并此时打印的是那个值。
def func1(): #这个是2个并列的函数,执行顺序就按照函数对奥用的顺序和执行顺序 print(111) def func2(): print(222) func1() func2() print(333) # 222 # 111 # 333
def func2(): print(222) def func3(): print(666) print(444) func3() print(888) print(333) func2() print(555) # 333 # 222 # 444 # 666 # 888 # 555
- 分析:当遇到函数的嵌套时,先看母函数(最外边那一层)定义函数名可以先跳过值接从上到下先找(print)或者调用函数()遇到那个就执行那个就好了,当遇到调用的函数内部有子函数时也是***层层降维,从上到下***.
5,关键字global和nonlocal
5.1>global在局部变量中调用全局定义好的变量来重新赋值.
a = 100 def func(): global a # 加了global表示不在局部创建这个变量而是直接使用全局的a # 并同时把局部值从新赋值给全局变量中拿过来的变量(全局变量和局部变量必须一致,不然拿不过来) # 此时的局部变量是局部变量赋的值 a = 28 print(a) func() print(a) # 28 # 28
- 5.2>nonlocal表示在局部作用中,调用非本局部中的变量,也不调用全局中的变量.(调用里它最近的一个相同名称的变量)还是"层层降维,从上到下"
a = 10 def func1(): a = 20 def func2(): nonlocal a a = 30 print(a) func2() print(a) func1() # 30 # 30