python函数的参数

位置参数

我们在利用函数计算一个数的平方时,必须要给这个函数传入一个参数——即我们要计算平方的数。

def pow(x):
    return x * x

对于函数pow来说,x就是一个位置参数,当调用这个函数时,x是必须传入有且唯一的一个参数。

当我们想计算 x3,可以定义另一个函数,那求x4呢,还要再定义吗,其实我们只需对pow函数稍加改动即可

def pow(x, n):
    prod = 1
    while n > 0:
        prod = prod * x
        n = n-1
    return prod

这时,x 和 n 就都是位置参数,在调用时必须同时传入,按照顺序依次赋值给x 和 n。

默认参数

在实际应用中我们必须考虑这种情况:一般求幂都是求平方,每次使用pow函数都要输入两个参数未免太麻烦了些,所以有了默认参数,即这个参数有个缺省值,在不输入是默认为缺省值。

【例1】:

def pow(x, n = 2):
    prod = 1
    while n > 0:
        prod = prod * x
        n = n-1
    return prod

当把n由变成n=2时,位置参数就变成了默认参数,当我们只传入一个参数时,n默认为2。即pow(3)计算的是32

对于其他n>2的情况,就必须要传入两个参数了。

使用默认参数有以下情况需要注意:

  • 函数的参数可以全由默认参数组成

  • 但当位置参数和默认参数同时存在时,默认参数必须定义在位置参数的后面,否则会报错

  • 如何设置默认参数:
    一般把变化大的设为位置参数,变化小的(默认值使用次数占多)设为默认参数,如【例1】 的pow函数

当有多个默认参数时,可以不按照默认参数的定义顺序给出,但必须同时给出参数名称,如【例2】:

【例2】:

def enroll(name, gender, age = 6, city = 'Beijing', district = 'Chaoyang'):
    print('name:', name)
    print('gender:', gender)
    print('age:', age)
    print('city:', city)
    print('district:', district)

我们可以这样调用:enroll('xiaoming', 'M', district = 'Jizhou', city = 'Tianjin')

运行结果:

name: xiaoming
gender: M
age: 6
city: Tianjin
district: Jizhou

重点:默认参数必须指向不变对象

【例3】:

def add_end(L = []):
    L.append('end')
    return L

当我们第一次运行该函数时,结果正常:

>>> add_end()
['end']

但当我们再运行时,会发现:

>>> add_end()
['end', 'end']
>>> add_end()
['end', 'end', 'end']

每次运行都会记录这个添加的end结尾,但这并非我们的本意,究竟为何如此呢?

我们定义的默认参数L是个变量,其指向为 [] 这个list,但运行一次之后,其指向的list内容发生了改变,已经变成['end'],默认参数的内容就变了,不再是函数定义时的 [] 了。

所以:

定义默认参数要牢记一点:默认参数必须指向不变对象!

有哪些数据类型是不变对象呢,比如:str,None,不变对象一旦创建,其内部数据便不可更改,减少了由于修改数据导致的错误。

可变参数

可变参数,顾名思义,就是传入参数的数量可以变化,可以是1个,2个,3个……

【例4】:

def cal(numbers):
    sum = 0
    for x in numbers:
        sum = sum + x
    return sum

由此我们可以计算1+2+4+5+8+...的值了,但每次调用我们传入的numbers参数必须是一个 list 或 tuple,较麻烦。此时的numbers是一个位置参数,不是可变参数。

稍加改动,即可将 numbers 定义为一个可变参数

【例4.1】

def cal(*numbers):
    sum = 0
    for x in numbers:
        sum = sum + x
    return sum

只是在numbers前加了个*,numbers就成为了可变参数,我们在调用此函数时可以这样调用:

cal(1,2,3,6,7,8),此时numbers接收到的是一个tuple,函数代码不变,函数即可传入任意个参数,包括0个参数。

>>> cal(3,56,7,8)
74
>>> cal()
0

如果numbers是位置参数时则0个参数会报错,因为位置参数是必须传入的。

当我已经有一个 list 或 tuple 了怎么把它传入函数中,可以这样做:

>>> num = [1,3,5,6,7,8]
>>> cal(*num)
30

在 list 或 tuple 前加一个*就能将其传入函数中了。

关键字参数

可变参数是可以传入任意个(包括0个)参数,这些可变参数在传入时会自动组装成一个tuple。关键字参数是允许你传入任意个(包括0个)含参数名的参数,这些关键字参数会自动组装成为一个dict

【例5】:

def person(name, age, **kw):
    print('name:', name, 'age:', age, kw)

函数person在调用时除了接受必选参数nameage,还接受关键字参数kw。调用时可以只传入位置参数

>>> person('xiaoming','6')
name: xiaoming age: 6 {}

也可以传入任意个数的关键字参数:

>>> person('xiaoming','6',city = 'Beijing', job = 'Engineer')
name: xiaoming age: 6 {'city': 'Beijing', 'job': 'Engineer'}

可以看到,两个关键字参数已经自动组成为dict了。

应用场景:

在用户注册时,用户可以只填入姓名,年龄两个参数,但提供城市,职业等参数选填。

与可变参数相同,我们也可以提前组装好一个dict,之后利用**dict名将其传入函数:

>>> d = { 'city' : 'Beijing', 'job' : 'Engineer'}
>>> person('xiaoming', 6, **d)
name: xiaoming age: 6 {'city': 'Beijing', 'job': 'Engineer'}

**d会将此dict的所有key-value用关键字参数传入到函数的**kw参数中,kw将获得一个dict,其获得的是d的一份拷贝,对**kw做任何改动不会影响d

命名关键字参数

关键字参数允许我们传入任意个含参数名的关键字参数,但是考虑到限制用户输入的随意性,如何让用户只传入规定的关键字参数呢。比如,只接受cityjob作为关键字参数,可以这样定义:

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

和关键字参数**kw不同,命名关键字参数只需要一个特殊分隔符**后面的参数都会被视为命名关键字参数。

调用方式如下:

>>> person('xiaoming',6,city = 'Beijing', job = 'Engineer')
xiaoming 6 Beijing Engineer

命名关键字参数调用时必须写参数名,不写的话函数会默认将其视为位置参数,将会报错。

如果命名关键字参数前面有可变参数,则省略*作为分隔符,可变参数后的参数自动视为命名关键字参数,不必担心混淆,命名关键字参数传入时必须包含参数名。

def person(name, age, *args , city, job):
    print(name, age,args, city, job)
>>> person('xiaoming',6, 'This is a smart boy', 'allergic to egg', city = 'Beijing', job = 'Engineer')
xiaoming 6 ('This is a smart boy', 'allergic to egg') Beijing Engineer

命名关键字参数也可以有缺省值,从而简化调用:

def person(name, age, *args , city = ‘Beijing, job):
    print(name, age,args, city, job)
>>> person('xiaoming',6, 'This is a smart boy', 'allergic to egg', job = 'Engineer')
xiaoming 6 ('This is a smart boy', 'allergic to egg') Beijing Engineer

注意:

使用命名关键字参数时,如果前面没有可变参数,必须加特殊分隔符*。如果不加,python将无法识别位置参数和命名关键字参数。

参数组合

这五种参数可以组合使用,但参数定义的顺序必须是:

位置参数-->默认参数-->可变参数-->命名关键字参数-->关键字参数

注意命名关键字参数和关键字参数的顺序。

比如定义一个函数,包含若干上述参数:

def f1(a, b, c=0, *args, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
def f2(a, b, c=0, *, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)

可以看出,

f1包含位置参数,默认参数,可变参数,关键字参数。

f2包含位置参数,默认参数,命名关键字参数,关键字参数。

其中可变参数在传入时自动组成一个tuple,关键字参数传入时自动组成一个dict。

函数调用时,python解释器会自动按参数位置和参数名把对应的参数传进去。

f1可以只传入位置参数,f2必须传入的有位置参数,命名关键字参数。

>>> f1(1,2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> f1(1,2,4)
a = 1 b = 2 c = 4 args = () kw = {}
>>> f1(1,2,c=4)
a = 1 b = 2 c = 4 args = () kw = {}
>>> f1(1,2,4,'ab',2)
a = 1 b = 2 c = 4 args = ('ab', 2) kw = {}
>>> f1(1,2,4,'ab',2,city = 'Beijing')
a = 1 b = 2 c = 4 args = ('ab', 2) kw = {'city': 'Beijing'}
>>> f2(1,2,4,d = 6)
a = 1 b = 2 c = 4 d = 6 kw = {}
>>> f2(1,2,4,d = 6,city = 'Beijing')
a = 1 b = 2 c = 4 d = 6 kw = {'city': 'Beijing'}
>>> f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}

最神奇的是,通过一个tuple和dict,你也可以调用上述函数:

>>> args = (1,2,3,4)
>>> kw = {'d':99,'x':'#'}
>>> f1(*args,**kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
>>> args = (1, 2, 3)
>>> kw = {'d':456,'city':'Beijing'}
>>> f2(*args,**kw)
a = 1 b = 2 c = 3 d = 456 kw = {'city': 'Beijing'}

无论函数是如何定义的,都可以通过类似func(*args,**kw)的方式调用它。

最后:

不要同时使用太多的组合,会使函数接口的可理解性很差

你可能感兴趣的:(python函数的参数)