DAY2-函数进阶

  • 函数参数--动态传参

  • gloabal, nonlocal关键字

  1. 函数参数--动态传参
  • 动态接收位置参数
    ⾸先我们先回顾一下位置参数, 位置参数, 按照位置进行传参。
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, in chi("⼤大⽶米饭", "⼩小⽶米饭", "⻩黄⽠瓜", "茄⼦子")
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("香蕉", "菠萝", "葫芦娃", "口罩") # 香蕉 菠萝 ('葫芦娃', '口罩') 娃哈哈 认值⽣生效

这个时候我们发现所有的默认值都⽣生效了. 这个时候如果不给出关键字传参. 那么你的默认值是永远都生效的.

顺序: 位置参数, 动态参数*, 默认值参
  1. 动态接收关键字参数
    在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"
  1. 关键字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     

你可能感兴趣的:(DAY2-函数进阶)