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

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': '#'}
    原文作者:晶爷传说
    原文地址: https://www.jianshu.com/p/3a6d610454d7
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞