**函数的参数** 函数定义中的参数有以下几种: * 必需参数(位置参数) * 默认参数 * 关键字参数 * 不定长参数 * 不定长关键字参数 **必需参数(位置参数)** * 必需参数(位置参数)必须以正确的顺序传入函数。调用时的数量必须和声明时的一样。 我们定义一个打招呼的函数 ~~~ #!/usr/bin/env python3 # -*- coding:utf-8 -*- def myHello(yourname,myname): '''定义招呼,需要依次传入对方的名字以及你的名字''' print("Hello",yourname,"my name is",myname) #第一次调用 myHello('lisa','airvip') #第二次调用 myHello() ~~~ 第一次调用,正确输出 ~~~ Hello lisa my name is airvip ~~~ 第二次调用,报了 缺少位置参数的错误 ~~~ Traceback (most recent call last): File "./test.py", line 10, in <module> myHello() TypeError: myHello() missing 2 required positional arguments: 'yourname' and 'myname' ~~~ **默认参数** * 默认参数在调用时可以传入也可以不传入 * 默认参数在函数定义时必须在位置参数之后 我们修改下打招呼的函数 ~~~ #!/usr/bin/env python3 # -*- coding:utf-8 -*- def myHello(yourname,myname = 'airvip'): '''定义招呼,需要依次传入对方的名字以及你的名字''' print("Hello",yourname,"my name is",myname) #第一次调用 myHello('lisa','air') #第二次调用 myHello('lisa') ~~~ 第一次调用与第二次调用都会正确输出 ~~~ Hello lisa my name is air Hello lisa my name is airvip ~~~ 可以看出添加了默认参数的函数调用相比只有位置参数的函数调用轻松多了。 **关键字参数** * 关键字参数是相对于函数调用来说的,我们用位置参数的例子来说明。 * 使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。 ~~~ #!/usr/bin/env python3 # -*- coding:utf-8 -*- def myHello(yourname,myname): '''定义招呼,需要依次传入对方的名字以及你的名字''' print("Hello",yourname,"my name is",myname) #第一次调用 myHello('lisa','airvip') #第二次调用 myHello('airvip','lisa') #第三次调用 使用关键字 myHello(myname='airvip',yourname='lisa') ~~~ 调用结果 ~~~ #第一次调用 Hello lisa my name is airvip #第二次调用 Hello airvip my name is lisa #第三次调用 使用关键字 Hello lisa my name is airvip ~~~ 我们不难发现,第一次调用与第三次调用返回的结果是一样的,然而第二次调用是没有使用关键字(定义函数时的形参),得到了与第一次和第三次调用不一样的结果。 **不定长参数** * 在函数处理是可能不确定有几个参数,我们就可以定义成不定长参数。 * 习惯上使用 *args 来表示不定常参数,当然你也可以使用其他前面加星的变量表示不定长参数。 * 如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。 * 不定长参数允许你传入 0 个或任意个参数,这些可变参数在函数调用时自动组装为一个 tuple。 以多个数字求和为例 ~~~ #!/usr/bin/env python3 # -*- coding:utf-8 -*- def mySum(*args): sum = 0 for i in args: sum += i print(sum) #调用 mySum() #打印0 mySum(1,2,3) #打印6 mySum(*(1,2,3)) #打印6 mySum(*[1,2,3]) #打印6 ~~~ **不定长关键字参数** * 习惯上使用 **kwargs 来表示不定长关键字参数,当然你也可以使用其他前面加双星的变量表示不定长关键字参数。 * Python 解释器会把通过 **kwargs 传入的参数变成一个 dict 形式。 以收集用户信息为例 ~~~ #!/usr/bin/env python3 # -*- coding:utf-8 -*- def userInfo(name,sex='男',*args,salary,**kwargs): '''用户信息收集''' print('用户信息'.center(20,'*')) info = """ 姓名:{_name} 性别:{_sex} 特征:{_args} 收入:{_salary} 其他: {_kwargs} """.format(_name = name,_sex = sex,_args = args,_salary = salary,_kwargs = kwargs) print(info) userInfo('airvip','男','喜欢女','长得帅',salary='1000000',address='山东') ~~~ 调用结果 ~~~ ********用户信息******** 姓名:airvip 性别:男 特征:('喜欢女', '长得帅') 收入:1000000 其他: {'address': '山东'} ~~~ 在 Python 中定义函数时,使用 必需参数(位置参数)、默认参数、不定长参数、关键字参数和不定长关键字参数,这5种参数的组合。但是参数定义的顺序必须是: 必需参数(位置参数)、默认参数、不定长参数、关键字参数和不定长关键字参数。 总结: 1. 使用了不定长参数默认参数就失效 2. *args 不定长参数,args 接收的是一个 tuple 3. **kwargs 不定长关键字参数,kwargs 接收的是一个 dict 4. 不定长参数既可以直接传入:func(1, 2, 3),又可以先组装 list 或 tuple ,再通过 *list 或 * tuple 传入 5. 不定长关键字参数既可以直接传入:func(a=1, b=2),又可以先组装 dict,再通过 **dict传入 **再谈默认参数** 默认参数很有用,但是使用不当又会产生不可思议的错误。 下面来探讨这个使用默认参数的例子 给列表末尾添加结束字符串: ~~~ #!/usr/bin/env python3 # -*- coding:utf-8 -*- def list_over(L = []): L.append('Over') return L #第一次调用 print(list_over([1,2,3])) #第二次调用 print(list_over([1,2,3])) #第三次调用 print(list_over()) #第四次调用 print(list_over()) ~~~ 调用结果 ~~~ [1, 2, 3, 'Over'] [1, 2, 3, 'Over'] ['Over'] ['Over', 'Over'] ~~~ 我们理想的结果是 第一次调用结果 等于 第二次调用 第三次调用结果 等于 第四次调用 然而,第三次调用结果 不等于 第四次调用 ,这是为什么呢? 因为 L 也是一个变量,该变量默认指向不变的内存地址空间,每次调用该函数,如果改变了该地址空间的值,则下次调用时,默认参数变量的内容就变了,但是该默认变量的指向没有发生改变,就造成了异常的结果。 所以,默认参数必须指向不变对象! 那问题来了,那该函数如何修改呢? ~~~ def list_over(L = None): if L == None: L = [] L.append('Over') return L ~~~ 这样无论使用默认参数调用多少次都不会改变默认变量 L 指向的内存空间的值了。