函数参数--动态传参
gloabal, nonlocal关键字
- 函数参数--动态传参
- 动态接收位置参数
⾸先我们先回顾一下位置参数, 位置参数, 按照位置进行传参。
def chi(quality_food, junk_food):
print("我要吃", quality_food, junk_food)
chi("⼤大⽶米饭", "⼩小⽶米饭")
结果:
我要吃 ('⼤大⽶米饭', '⼩小⽶米饭')
# "⼤大⽶米饭"传递给quality_food "⼩小⽶米饭"传递给junk_food
现在问题来了. 我想吃任意的食物. 数量是任意的, 食物也是任意的. 这时我们就要⽤用到 动态参数了.
在参数位置编写*表⽰示接收任意内容
def chi(*food):
print("我要吃", food)
chi("⼤大⽶米饭", "⼩小⽶米饭")
结果:
我要吃 ('⼤大⽶米饭', '⼩小⽶米饭')
# 多个参数传递进去. 收到的内容是元组tuple
动态接收参数的时候要注意: 动态参数必须在位置参数后⾯
def chi(*food,a,b):
print("我要吃",food,a,b)
chi("大米","小米","红烧肉","茄子")
这时程序运⾏行行会报错. 因为前⾯面传递进去的所有位置参数都被*food接收了了. a和b永远接收 不到参数
Traceback (most recent call last):
File"/Users/sylar/PycharmProjects/oldboy/fun.py", line 95, inchi("⼤大⽶米饭", "⼩小⽶米饭", "⻩黄⽠瓜", "茄⼦子")
TypeError: chi() missing 2 required keyword-only arguments: 'a' and 'b'
所以必须改写成以下代码:
def chi(*food, a, b):
print("我要吃", food, a, b)
chi("⼤大⽶米饭", "⼩小⽶米饭", a="⻩黄⽠瓜", b="茄⼦子") # 必须⽤用关键字参数来指定
这个时候a和b就有值了了, 但是这样写呢位置参数就不能⽤用了了. 所以. 我们要先写位置参数, 然后再⽤动态参数.
def chi(a, b, *food):
print("我要吃", a, b, food)
chi("⼤大⽶米饭", "⼩小⽶米饭", "馒头", "⾯面条")
# 前两个参数用位置参数来接收, 后面的参数⽤动态参数接收.
那默认值参数呢?
def chi(a, b, c='馒头', *food):
print(a, b, c, food)
chi("⾹蕉", "菠萝") # ⾹蕉 菠萝 馒头 (). 默认值⽣生效
chi("香蕉", "菠萝", "葫芦娃") # 香蕉 菠萝 葫芦娃 () 默认值不不⽣生效
chi("⾹蕉", "菠萝", "葫芦娃", "口罩") # 香蕉 菠萝 葫芦娃 ('⼝罩',) 默认值不生效
发现默认值参数写在动态参数前面. 默认值只有一种情况可能会生效.
def chi(a, b, *food, c="娃哈哈"):
print(a, b, food, c)
chi("⾹蕉", "菠萝") # 香蕉 菠萝 () 娃哈哈 默认值⽣生效
chi("香蕉", "菠萝", "葫芦娃") # 香蕉 菠萝 ('葫芦娃',) 娃哈哈 默认值⽣生效
chi("香蕉", "菠萝", "葫芦娃", "口罩") # 香蕉 菠萝 ('葫芦娃', '口罩') 娃哈哈 认值⽣生效
这个时候我们发现所有的默认值都⽣生效了. 这个时候如果不给出关键字传参. 那么你的默认值是永远都生效的.
顺序: 位置参数, 动态参数*, 默认值参
- 动态接收关键字参数
在python中可以动态的位置参数, 但是这种情况只能接收位置参数⽆法接收关键字参数.
在python中使⽤*来接收动态关键字参数
def func(**kwargs):
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)
- 所以关键字参数必须在位置参数后面. 由于实参是这个顺序. 所以形参接收的时候也是这个顺序. 也就是说位置参数必须在关键字参数前面. 动态接收关键字参数也要在后⾯.
最终顺序(*):
位置参数 > *args > 默认值参数 > **kwargs
这四种参数可以任意的进⾏行行使⽤用. 如果想接收所有的参数:
def func(*args, **kwargs):
print(args, 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:param food: 参数food是什什么意思 :param:param drink: 参数drink是什什么意思
:return:return: 返回的是什么东东
"""
print(food, drink)
return "very good"
- 关键字global和nonlocal
- ⾸先我们写这样⼀个代码, 首先在全局声明⼀一个变量, 然后再局部调⽤用这个变量, 并改变这 个变量的值
a = 100
def func():
global a # 加了了个global表示不不再局部创建这个变量量了了. 而是直接使用全局的a
a = 28
print(a)
func()
print(a)
global表示. 不再使用局部作⽤域中的内容了. ⽽改用全局作用域中的变量
nonlocal 表⽰在局部作用域中, 调⽤用父级命名空间中的变量
a = 10
def func1():
a = 20
def func2():
nonlocal a
a = 30
print(a)
func2()
print(a)
func1()
结果:
加了nonlocal
30
30
不加nonlocal
30
20