Python自学之路之day09-函数的进阶
一、函数参数--动态传参
动态传参分为两种:
1、动态接收位置参数
熟悉下之前说的位置传参:
def food(good_food,fruit): print("我要吃:",good_food,fruit) food("米饭","西瓜") # 按照位置顺序,把值传给函数对应的形参。
现在问题来了,我想吃任意的食物,数量是任意的,食物也是任意的.这时我们就要用到动态参数了.
在参数位置编写*表示接收任意内容:
def food(*food): print("我要吃:",food) food("米饭","西瓜") 打印结果: 我要吃: ('米饭', '西瓜') 结论:传递多个参数,会返回一个元祖。
动态接收参数的时候要注意: 动态参数必须在位置参数后面:
## 错误位置参数
def food(*food,fruit): print("我要吃:",food,fruit) food("米饭","小米","苹果")
打印结果:
程序会报错,因为前面传递进去的所有位置参数都被*food接收了furit永远接收不到参数
## 正确位置参数
def food(*food,fruit):
print("我要吃:",food,fruit)
food("米饭","小米",fruit="苹果") ## 用关键字指定
打印结果:
我要吃: ('米饭', '小米') 苹果
### 但是这种写法,位置参数就不能⽤了,所以.我们要先写位置参数,然后再用动态参数
def food(fruit,*food):
print("我要吃:",fruit,food)
food("苹果","米饭","小米") # 前两个参数用位置参数来接收, 后面的参数用动态参数接收
默认值与动态传参
def food(fruit,*food,drank="可乐"): print("我要吃:",fruit,food,drank) food("苹果") food("苹果","米饭","小米") 打印结果: 我要吃: 苹果 ('米饭', '小米') 可乐 我要吃: 苹果 () 可乐
可以看到,默认值都生效了。
参数顺序:位置参数, 动态参数*, 默认值参数
2、动态接收关键字参数
在python中可以动态的接收位置参数, 但是*这种情况只能接收位置参数无法接收关键字参数.
在python中使用**来接收动态关键字参数:
def fn(**kwargs): print(kwargs) fn(a=1,b=2,c=3) fn(a=1,b=2) 打印结果: {'a': 1, 'b': 2, 'c': 3} {'a': 1, 'b': 2}
通过结果我们可以发现,打印的结果为字典类型。
最终函数顺序:位置参数 > *args > 默认值 > **kwargs
如果想接收所有的参数:
def fn(*args,**kwargs): print(args) print(kwargs) fn("kele",a=1,b=2) 打印结果: ('kele',) {'a': 1, 'b': 2}
3、动态传参的另一种方式
def fn(*args): print(args) lst = [1,2,4,6] fn(lst[0],lst[1],lst[2],lst[3]) fn(*lst) ##可以使用*把一个列表按顺序打散(结构) s = "我不好说" ## 字符串也可以 fn(*s) 打印结果: (1, 2, 4, 6) (1, 2, 4, 6) ('我', '不', '好', '说')
在实参位置上给一个序列,列表,可迭代对象前面加个*表示把这个序列按顺序打散.在形参的位置上的* 表示把接收到的参数组合成⼀个元组。
如果是一个字典, 那么也可以打散. 不过需要用两个*
def fn(**kwargs): print(kwargs) dic = {"a":"可乐","b":"许碧"} fn(**dic)
二、命名空间
在python解释器开始执行之后, 就会在内存中开辟一个空间, 每当遇到一个变量的时候, 就把变量名和值之间的关系记录下来,
但是当遇到函数定义的时候,解释器只是把函数名读入内存, 表示这个函数存在了,至于函数内部的变量和逻辑, 解释器是不关心的.
也就是说一开始的时候函数只是加载进来, 仅此而已, 只有当函数被调用和访问的时候, 解释器才会根据函数内部声明的变量来进行开辟变量的内部空间.
随着函数执行完毕, 这些函数内部变量占用的空间也会随着函数执行完毕而被清空.
例如:
def fn(): a = 10 print(a) fn() print(a) ## 此时a已经不存在了
我们给存放名字和值的关系的空间起一个名字叫: 命名空间.我们的变量在存储的时候就是存储在这片空间中的
命名空间分类:
2. 局部命名空间--> 在函数中声明的变量会放在局部命名空间
3. 内置命名空间--> 存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置命名空间
1. 内置命名空间
2. 全局命名空间
3. 局部命名空间(函数被执行的时候)
取值顺序:
1. 局部命名空间
2. 全局命名空间
3. 内置命名空间
a = 20 def fn(): a = 10 print(a) fn() 打印结果: 10
作用域: 作用域就是作用范围, 按照生效范围来看分为全局作用域和局部作用域.
全局作用域: 包含内置命名空间和全局命名空间.在整个文件的任何位置都可以使用(遵循从上到下逐行执行).
局部作用域: 在函数内部可以使用.
作用域命名空间:
1. 全局作用域: 全局命名空间 + 内置命名空间
2. 局部作用域: 局部命名空间
我们可以通过globals()函数来查看全局作用域中的内容, 也可以通过locals()来查看局部作用域中的变量和函数信息
a =10 def fn(): a = 40 b = 20 def fn1(): print("哈哈") print(a,b) # 这里使用的事局部作用域 print(globals()) # 打印全局作用域中的内容 print(locals()) # 打印局部作用域中的内容 fn()
##打印结果
40 20
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000194884285F8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/Django/PythonExercise/day10/01.py', '__cached__': None, 'a': 10, 'fn': <function fn at 0x0000019488321E18>}
{'fn1': <function fn.<locals>.fn1 at 0x0000019488500AE8>, 'b': 20, 'a': 40}
三、函数嵌套
1. 只要遇见了()就是函数的调用. 如果没有()就不是函数的调用
2. 函数的执行顺序
def fn3(): print(333) def fn4(): print(444) print(666) fn4() print(888) print(333) fn3() print(555) 打印结果: 333 333 666 444 888 555 总结:注意函数的执行顺序
四、global和nonlocal
首先我们写这样一个代码:首先在全局声明一个变量, 然后再局部调用这个变量,并改变这个变量的值:
a = 100 def fn(): global a # 加了个global表示不再局部创建这个变量了,而是直接使用全局的a a =28 print("我在函数内部:",a) fn() print("我在函数外部:",a) 打印结果: 我在函数内部: 28 我在函数外部: 28
global表⽰. 不再使用局部作用域中的内容了了. 而改用全局作用域中的变量,若是内部出现该变量内容,则会修改并同步到外部。
lst = ["可乐","雪碧","美年达"] def fn(): lst.append("mayunyun") # 对于可变数据类型可以直接进行访问.但是不能改地址,就是不能赋值。 print(lst) fn() print(lst)
nonlocal 表示在局部作用域中, 调用父级命名空间中的变量。
## 加nonlocal
a = 10 def fn1(): a =20 def fn2(): nonlocal a a = 30 print(a) fn2() print(a) fn1() 打印结果: 30 30
## 不加nonlocal
a = 10
def fn1():
a =20
def fn2():
a = 30
print(a)
fn2()
print(a)
fn1()
打印结果:
30
20
再看,如果嵌套了很多层,会是一种什么效果:
a = 1 def fn1(): a = 2 def fn2(): nonlocal a a = 3 def fn3(): a = 4 print(a) print(a) fn3() print(a) print(a) fn2() print(a) print(a) fn1() print(a)
打印结果:
1
2
3
4
3
3
1
注意分析,各个打印值对应的print。

浙公网安备 33010602011771号