【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)的方式调用它。

最后:

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 本文是来自廖大的python教程其中我一直忘记的部分。算是一个笔记把。因为日常这俩参数名字一直搞混 可变参数 在P...
    东皇Amrzs阅读 56,986评论 7 65
  • 1.函数参数 1.1 位置参数 我们先写一个计算x2的函数: 对于power(x)函数,参数x就是一个位置参数。当...
    时间之友阅读 368评论 0 2
  • python函数的参数是目前见过最复杂的参数了。 C语言里用的最多的可变参数函数就是scanf和printf了,j...
    米耳阅读 349评论 0 0
  • Python 是一种相当高级的语言,通过 Python 解释器把符合语法的程序代码转换成 CPU 能够执行的机器码...
    Python程序媛阅读 1,889评论 0 3
  • 本章将介绍函数中参数的用法,更多内容请参考:Python学习指南 定义函数的时候,我们把参数的名字和位置确定下来,...
    小七奇奇阅读 164评论 0 2