函数的进阶

一.动态参数

1.位置参数的动态参数: *args  多个参数传递进去. 收到的内容是元组tuple

在参数位置编写  *  表⽰接收任意内容

def chi(*food):
print("我要吃", food)
chi("⼤⽶饭", "⼩⽶饭")
结果:
我要吃 ('⼤⽶饭', '⼩⽶饭')   # 多个参数传递进去. 收到的内容是元组tuple
def func(a, b, c, *args, d = 5):
    print(a, b, c, d, args)

func(1,2,3)
func(1,2,3,4,5,6,7, d ="马大哈")
结果为:
1 2 3 5 ()
1 2 3 马大哈 (4, 5, 6, 7)
# 写函数. 给函数传递任意个整数. 返回这些数的和

def he(*n):
    sum = 0
    for e in n:
        sum += e
    return sum
print(he(1,2,3,4,5))
结果:  15

2.顺序:   位置参数 > *args > 默认值 > **kwargs

def chi(*food, a, b):
print("我要吃", food, a, b)
chi("⼤⽶饭", "⼩⽶饭", "⻩⽠", "茄⼦")

这时程序运⾏会报错. 因为前⾯传递进去的所有位置参数都被*food接收了. a和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("⾹蕉", "菠萝", "葫芦娃", "⼝罩") # ⾹蕉 菠萝 ('葫芦娃', '⼝罩') 娃哈哈 默
认值⽣效

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

结论:   位置参数 > *args > 默认值 > **kwargs

3. 动态接收关键字参数

在python中使⽤  **  来接收动态关键字参数,这个时候接收的是⼀个dict

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}

注意:在函数调⽤的时候, 如果先给出关键字参数, 则整个参数列表会报错.

def func(a, b, c, d):
 print(a, b, c, d)
# 关键字参数必须在位置参数后⾯, 否则参数会混乱
func(1, 2, c=3, 4)
此时会报错:
File "D:/老男孩课堂笔记/day10/code/03 动态传参.py", line 79
    func(1, 2, c=3, 4)
                   ^
SyntaxError: positional argument follows keyword argument

这四种参数可以任意的进⾏使⽤. 如果想接收所有的参数:

def func(*args, **kwargs):
print(args, kwargs)
func("麻花藤","⻢晕",wtf="胡辣汤")

4.  在形参上 * 聚合, ** 聚合  ,在实参上 * 打散,  ** 打散

 

思考:把列表中的每一个元素作为参数, 传递给函数. 一次都传过去

def func(*args, **kwargs):  # *表示聚合,所有的位置参数, 聚合成元组 **聚合成字典
    print(args)
    print(kwargs)
lst = ["马虎疼", "大洋哥", "小花生", "毛尖妹妹"]
func(*lst)  # 实参, 打散, 迭代产生的

dic = {"name":"太白", "alex":"wuse"}
func(**dic) # 把字典打散. 以key=value形式进行传参

结果为:
('马虎疼', '大洋哥', '小花生', '毛尖妹妹')
{}
()
{'alex': 'wuse', 'name': '太白'}

5.函数的注释:

def chi(food, drink):
 """
 这⾥是函数的注释, 先写⼀下当前这个函数是⼲什么的, ⽐如我这个函数就是⼀个吃
 :param :param food: 参数food是什么意思
 :param :param drink: 参数drink是什么意思
 :return :return: 返回的是什么东东
 """
 print(food, drink)
 return "very good"

二.命名空间和作用域

1.globals()  和 locals()

我们可以通过globals()函数来查看全局作⽤域中的内容, 也可以通过locals()来查看局部作
⽤域中的变量和函数信息:

a = 10
def func():
    a = 20
    print(a)    # 就近原则
    print(globals())  # globals() 获取到全局作用域(内置,全局)中的所有名字
    print(locals())  # locals() 查看当前作用域中的所有名字
func()

2.关键字global和nonlocal

global表⽰. 不再使⽤局部作⽤域中的内容了. ⽽改⽤全局作⽤域中的变量

a = 100  全局
def func():
    global a # 加了个global表示不再局部创建这个变量了. ⽽是直接使⽤全局的a
    a = 28   此时全局中的''a'' 已经被引用,并被更改
    print(a)
func()
print(a)  

结果为:
28
28

nonlocal 表⽰在局部作⽤域中, 调⽤⽗级(离当前变量最近的上一级)命名空间中的变量.:

def func1():
    a = 20
    def func2():
        nonlocal a
        a = 30
        print(a)
    func2()
    print(a)
func1()
结果为:
加了nonlocal
30
30
不加nonlocal
30
20

 

3.函数的嵌套

原则:

1. 只要遇⻅了()就是函数的调⽤. 如果没有()就不是函数的调⽤

2. 函数的执⾏顺序

自己分析一下下面输出什么:

def func1():
    print("")
    def func2():
        print("")
        def func3():
            print("")
        print("")
    def func4():
        print("哈哈")
        func2()
    print("")
    func2()
func1()
结果为:
赵
周
钱
李
def func1():
    print("呵呵")
    def func2():
        print("哈哈")
    func2()
    print("吼吼")
func1() 
  结果为:
呵呵
哈哈
吼吼

 

posted @ 2018-07-13 16:21  shuai1993  阅读(184)  评论(0编辑  收藏  举报