美文网首页廖雪峰的python基础教程学习笔记
Python学习笔记(六)函数的参数

Python学习笔记(六)函数的参数

作者: 晶爷传说 | 来源:发表于2018-02-22 13:07 被阅读0次

    1.位置参数

    调用函数时,传入的值按照参数的位置顺序依次赋给参数。

    2.默认参数

    默认参数很有用,但是使用不当可能掉坑里,默认参数有个最大的坑,如下:

    def add_end(L=[]):
    L.append('End')
    return L
    使用默认参数时,结果是正确的:
    >>>add_end()
    ['End']
    但是,再次调用时,结果就不对了:
    >>>add_end()
    ['End', 'End']
    >>>add_end()
    ['End', 'End', 'End']
    原因:Python函数在定义时,默认参数L的值就被计算出来了,即[],因为L也是一个变量,它指向对象[],每次调用该函数,如果改变了[]的内容,则下次调用时,默认参数的内容就变了,不再是[]了。
    解决方案:使用None这个不变对象来实现

    def add_end(L=None):
        if L is None:
            L = []
        L.append('END')
        return L
    无论怎么调用都不会出错:
    >>>add_end()
    ['End']
    >>>add_end()
    ['End']
    

    为什么要设计str、None这样的不变对象呢。不变对象一旦创建,对象内部的数据就不能修改,这样就减少了因为修改数据导致的错误,此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。编写程序时,如果能设计一个不变对象,尽量设计成不变对象。

    3.可变参数

    即传入的参数个数是可变的。以一个数学题为例,给定一组数字a,b,c...,计算a2+b2+c2+...
    要定义出这个函数,我们必须确定输入的参数,由于参数个数不确定,可以想到把a,b,c作为一个list或tuple传进来,如下:

    def calc(numbers):
        sum = 0
        for n in numbers:
            sum = sum + n*n
        return sum
    >>>calc([1,2,3])
    14
    >>>calc([])
    0
    

    利用可变参数,可变为如下:

    def calc(*numbers):
        sum = 0
        for n in numbers:
            sum = sum + n*n
        return sum
    >>>calc(1,2,3)
    14
    >>>calc()
    0
    

    如有一已知的list或tuple,调用时前面加*号:

    list1 = [1,2,3]
    >>>calc(*list1)
    14
    

    4.关键字参数

    关键字参数允许传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
    函数person除了必选参数nameage外,还接受关键字参数kw,在调用函数时,可以只传入必选参数,也可以传入任意个的关键字参数:

    test.py:
    def person(name, age, **kw):
        print('name:', name, 'age:', age, 'other:', kw)
    
    extra = {'city': 'Beijing', 'job': 'Engineer'}
    person('Tom', 40)
    person('Jack', 25, city='Beijing', job = 'Engineer')
    person('Jack', 25, **extra)
    
    iTerm终端:
    >>>python3 ~/python_test/test.py
    name: Tom age: 40 other: {}
    name: Jack age: 25 other: {'city': 'Beijing', 'job': 'Engineer'}
    name: Jack age: 25 other: {'city': 'Beijing', 'job': 'Engineer'}
    注意:kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外地extra。
    

    关键字参数可以扩展函数功能,比如用在用户注册信息时,有些信息是必填项,有些信息是选填项。

    5.命名关键字参数

    对于关键字参数,函数调用者可以传入任意不受限制的关键字参数,至于到底传入了哪些,需要在函数内部进行检查:

    test.py:
    def person(name, age, **kw):
        if 'city' in kw:
            print("there is a 'city' key")
        if 'job' in kw:
            print("there is a 'job' key")
        print('name:', name, 'age:', age, 'other:', kw)
    
    extra = {'city': 'Beijing', 'job': 'Engineer'}
    person('Tom', 40)
    person('Jack', 25, **extra)
    
    iTerm终端:
    >>>python3 ~/python_test/test.py
    name: Tom age: 40 other: {}
    there is a 'city' key
    there is a 'job' key
    name: Jack age: 25 other: {'city': 'Beijing', 'job': 'Engineer'}
    

    但是调用者仍然可以传入不受限制的关键字参数,如果要限制关键字参数的名字,就可以使用命名关键字参数,例如,只接收cityjob作为关键字参数,则定义如下:

    def person(name, age, *, city, job):
        print(name, age, city, job)
    

    和关键字参数**kw不同,命名关键字参数需要一个特殊的分隔符**后面的参数视为命名关键字参数,其调用如下:

    >>>person('Jack', 25, city='Beijing', job = 'Engineer')
    Jack 25 Beijing Engineer
    

    如果函数定义中已经有一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊的分隔符*了:

    # ~/python_test/test.py
    def person(name, age, \*args, city, job):
        print(name, age, args, city, job)
    person('Jack', 24, 'Beijing', 'Engineer')
    

    命名关键字参数必须传入参数名,这和位置参数不同,如果没有传入参数名,系统将报错:

    >>>python3 ~/python_test/test.py
    Traceback (most recent call last):
      File "/Users/lijing/python_test/test.py", line 4, in <module>
        person('Jack', 25, 'Beijing', 'Engineer')
    TypeError: person() missing 2 required keyword-only arguments: 'city' and 'job'
    

    由于调用时缺少参数名cityjob,python解释器把四个参数都视为了位置参数,但是person函数只接受nameage两个位置参数,因此报错。此外命名关键字参数还可以使用默认缺省值:

    def person(name, age, *, city = 'Beijing', job):
        print(name, age, city, job)
    

    调用时可以不传入city参数,使用默认值'Beijing'
    注意:使用命名关键字时,要特别注意*的使用,没有可变参数时必须加一个*作为特殊分隔符,如果缺少*,python解释器将无法识别位置参数和命名关键字参数。

    6.参数组合

    在python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用,但注意参数定义顺序必须是必选参数、默认参数、可变参数、命名关键字参数、关键字参数:
    函数在调用时,python解释器自动按照参数位置和参数名把对应的参数传进去,而且,通过一个tuple和dict,也可以调用该函数:

    # ~/python_test/test.py
    def f1(a, b, c=0, *args, **kw):
        print(a, b, c, args, kw)
    def f2(a, b, c=0, *, d, **kw):
        print(a, b, c, d, kw)
    args = {1, 2, 3}
    kw = {'d':99, 'x':'#'}
    
    f1(1,2)
    f1(1,2,c=3)
    f1(1,2,3,'a','b')
    f1(1,2,3,'a','b',x=99)
    f2(1,2,d=99,ext=None)
    f1(*args, **kw)
    f2(*args, **kw)
    
    #iTerm2终端:
    >>>python3 ~/python_test/test.py
    1 2 0 () {}
    1 2 3 () {}
    1 2 3 ('a', 'b') {}
    1 2 3 ('a', 'b') {'x': 99}
    1 2 0 99 {'ext': None}
    1 2 3 () {'d': 99, 'x': '#'}
    1 2 3 99 {'x': '#'}
    

    相关文章

      网友评论

        本文标题:Python学习笔记(六)函数的参数

        本文链接:https://www.haomeiwen.com/subject/dkzatftx.html