![](https://i-blog.csdnimg.cn/blog_migrate/10c22d581b4540b702960a0aed70c163.png)
引言
Python的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数
# 1.无返回值、参数的函数
def fn1():
print('Hello World!')
fn1() # Hello World!
# 2.带返回值、无参数的函数
def fn2():
data = 'Hello World!'
return data
fn2() # 'Hello World!'
# 3.带一个参数(无默认值)的函数
def fn3(data):
res = 'Hello ' + data
return res
fn3('World!') # 'Hello World!'
# 4.带有多个参数(无默认值)的函数
def fn4(name, age):
res = '我叫' + name + ',今年' + str(age) + '岁'
return res
fn4('Andy',18) # '我叫Andy,今年18岁'
# 注意:一定要按照原来形参的顺序传递
fn4('20','Harry') # '我是20,今年Harry岁'
fn4(name='Tom',age=20) # '我叫Tom,今年20岁'
fn4(age=20,name='Tom') # '我叫Tom,今年20岁'
fn4('Tom',age=20) # '我叫Tom,今年20岁'
# 注意:在调用的时候还是要按照原函数中的顺序,否则会报错
fn4(age=20,'Tom') # 报错
# 5.参数设置默认值(一个参数)的函数
def fn5(name='Lee'):
res = 'Hello ' + name
return res
fn5() # 'Hello Lee'
fn5('Andy') # 'Hello Andy'
fn5(name='Andy') # 'Hello Andy'
# 6.参数设置默认值(多个参数)的函数
def fn6(name='Jack', age=20):
res = '我叫' + name + ',今年' + str(age) + '岁'
return res
fn6() # '我叫Jack,今年20岁'
fn6(name='Harry') # '我叫Harry,今年20岁'
fn6(age=22) # '我叫Jack,今年22岁'
fn6(name='Rita',age=25) # '我叫Rita,今年25岁'
# 7.部分参数使用默认值的函数
def fn7(name, age=20):
res = '我叫' + name + ',今年' + str(age) + '岁'
return res
fn7('Rita') # '我叫Rita,今年20岁'
fn7(name='Rita') # '我叫Rita,今年20岁'
fn7('Rita',23) # '我叫Rita,今年23岁'
fn7('Rita',age=23) # '我叫Rita,今年23岁'
fn7(age=23,'Rita') # 报错
fn7(age=23,name='Rita') # '我叫Rita,今年23岁'
# 8.带有*args参数的函数
def fn8(*args):
data = args
return data
fn8() # ()
fn8(178) # (178,)
fn8(178,185) # (178, 185)
def height(*args):
# 对args中的元素进行循环操作
for data in args:
print("身高是:{}m".format(data / 100))
'''
身高是:1.71m
身高是:1.85m
'''
height(171,185)
# 9.带有**kwargs参数的函数
def fn9(**kwargs):
data = kwargs
print(data)
fn9() # {}
fn9(name='Andy') # {'name': 'Andy'}
fn9(name='Harry',age=24) # {'name': 'Harry', 'age': 24}
def information(**kwargs):
for key,val in kwargs.items():
print("{0} = {1}".format(key,val))
information(name='Andy') # name = Andy
'''
name = Vanly
age = 18
height = 170
'''
information(name='Vanly', age=18, height=170)
# 10.带有形参和*args参数的函数
def fn10(x, *args):
print("x:",x)
print("args:",args)
'''
x: 1
args: ()
'''
fn10(1)
'''
x: 1
args: (2,)
'''
fn10(1,2)
'''
x: 1
args: ()
'''
fn10(1,2,3,4)
'''
x: 1
args: (2, 3, 4, 'Andy')
'''
fn10(1,2,3,4,'Andy')
# 11.带有形参和**kwargs参数的函数
def fn11(x, **kwargs):
print("x:",x)
print("kwargs:",kwargs)
'''
x: 1
kwargs: {}
'''
fn11(1)
'''
x: 1
kwargs: {'name': 'Andy'}
'''
fn11(1,name='Andy')
'''
x: 1
kwargs: {'name': 'Andy', 'age': 18}
'''
fn11(1,name='Andy',age=18)
# 12.带有形参 + *args参数 + **kwargs参数的函数
def fn12(x, *args, **kwargs):
print("x:",x)
print("args:",args)
print("kwargs:",kwargs)
'''
x: 1
args: ()
kwargs: {}
'''
fn12(1)
'''
x: 1
args: (2, 3)
kwargs: {}
'''
fn12(1,2,3)
'''
x: 1
args: ()
kwargs: {'name': 'Andy', 'age': 18}
'''
fn12(1,name='Andy',age=18)
'''
x: 1
args: (2, 3)
kwargs: {'name': 'Andy', 'age': 18}
'''
fn12(1,2,3,name='Andy',age=18)
'''
x: 1
args: (2, 3)
kwargs: {'name': 'Andy', 'age': 18}
'''
kwargs = {'name':'Andy', 'age':18}
fn12(1,2,3,**kwargs)
1.位置参数
编写一个计算的函数
def power(x):
return x * x
对于power(x)函数,参数x就是一个位置参数
当我们调用power(x)函数时,必须传入有且仅有的一个参数x
power(5) # 25
power(10) # 100
编写一个计算的函数
def power(x, n):
res = 1
while n > 0:
n = n - 1
res = res * x
return res
对于这个修改后的power(x,n)函数,可以计算任意n次方
修改后的power(x,n)函数有两个参数:x和n,这两个参数都是位置参数,调用函数时,传入的两个值按照位置顺序依次赋给参数x和n
# 5的3次方
power(5,3) # 125
# 10的4次方
power(10,4) # 10000
2.默认参数
def power(x, n):
res = 1
while n > 0:
n = n - 1
res = res * x
return res
# TypeError: power() missing 1 required positional argument: 'n'
power(5)
Python的错误信息很明确: 调用函数power()缺少了一个位置参数n
针对上述出现无法正常调用power(x,n)函数的情况,由于我们经常计算,所以完全可以把第二个参数n的默认值设定为2(设置默认参数)
# 默认参数可以简化函数的调用,降低调用函数的难度
def power(x, n=2):
res = 1
while n > 0:
n = n - 1
res = res * x
return res
# 调用power(5)相当于调用power(5,2)
power(5) # 25
power(5,2) # 25
而对于n > 2的其他情况,就必须明确地传入n
def power(x, n=2):
res = 1
while n > 0:
n = n - 1
res = res * x
return res
# 5的3次方
power(5,3) # 125
设置默认参数注意点
1. 必选参数在前,默认参数在后,否则Python的解释器会报错
2.当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面,其中变化小的参数就可以作为默认参数
例如,编写一个大学新生注册信息登记的函数
def students(name, gender): print('姓名:', name) print('性别:', gender) # 调用students()函数只需要传入两个参数 ''' 姓名: Odin 性别: M ''' students('Odin','M')
如果要继续传入年龄、省份等信息怎么办?这样会使得调用函数的复杂度大大增加
我们可以把年龄和省份设为默认参数
def students(name, gender, age=18, province='广东'): print('姓名:', name) print('性别:', gender) print('年龄:', age) print('省份:', province)
上述操作,可使大多数学生注册时不需要提供年龄和省份,只需提供必须的两个参数
''' 姓名: Harry 性别: M 年龄: 18 省份: 广东 ''' students('Harry','M')
只有与默认参数不符的学生才需要提供额外的信息
''' 姓名: Lee 性别: F 年龄: 19 省份: 广东 ''' students('Lee', 'F', 19) ''' 姓名: Summer 性别: F 年龄: 18 省份: 安徽 ''' students('Summer', 'F', province='安徽')
可见,默认参数降低了函数调用的难度
有多个默认参数时,调用的时候可以按顺序提供默认参数
# 调用students('Bob', 'M', 7),意思是,除了name,gender这两个参数外,最后1个参数应用在参数age上, # province参数由于没有提供,仍然使用默认值 ''' 姓名: Bob 性别: M 年龄: 20 省份: 广东 ''' students('Bob', 'M', 20)
也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上
''' 姓名: Ruby 性别: F 年龄: 18 省份: 湖南 ''' students('Ruby', 'F', province='湖南')
注意: 定义默认参数要牢记一点,默认参数必须指向不变对象
定义一个函数add_res,传入一个list,添加一个H再返回结果
def add_res(res=[]):
res.append('H')
return res
# 正常调用不会出错
add_res([1, 2, 3]) # [1, 2, 3, 'H']
add_res(['x','y','z']) # ['x', 'y', 'z', 'H']
# 第一次使用默认参数调用不出错
add_res() # ['H']
# 再次调用add_res()出错
add_res() # ['H', 'H']
add_res() # ['H', 'H', 'H']
Python函数在定义的时候,默认参数res的值就被计算出来了,即[]
,因为默认参数res也是一个变量,它指向对象[]
,每次调用该函数,如果改变了res的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]
默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!
解决上述问题代码如下所示:
def add_res(res=None):
if res is None:
res = []
res.append('H')
return res
add_res() # ['H']
add_res() # ['H']
add_res() # ['H']
3.可变参数(*args)
可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个参数
问题: 给定一组数字a,b,c……,请计算
def calc(*args):
sum = 0
for n in args:
sum = sum + n * n
return sum
定义可变参数在参数前面加了一个 *号
调用calc函数时,可以传入任意个参数,包括0个参数
calc() # 0
calc(1,2,3) # 14
calc(1,3,5,7) # 84
调用函数时,可变参数既可以直接传入,又可以先组装成列表list或元组tuple,再通过*args传入
# *nums表示把nums这个list的所有元素作为可变参数传进去
nums = [1, 2, 3]
calc(*nums) # 14
可变参数允许传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple元组
注意:
*args是可变参数,args接收的是一个元组tuple
使用*args是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法
4.关键字参数(**kwargs)
关键字参数允许传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict字典
关键字参数可以扩展函数的功能
def person(name, age, **kwargs):
print('name:', name, 'age:', age, 'info:', kwargs)
函数person除了必选参数name和age外,还接受关键字参数kwargs
# name: Andy age: 25 info: {}
person('Andy', 25)
# name: Lee age: 26 info: {'city': 'GuangZhou'}
person('Lee', 26, city='GuangZhou')
# name: Rita age: 30 info: {'gender': 'M', 'job': 'Engineer'}
person('Rita', 30, gender='M', job='Engineer')
调用函数时,关键字参数既可以直接传入,又可以先组装成dict字典,再通过**kwargs传入
'''
**extra表示把extra这个dict的所有key-value用关键字参数传入到函数的**kwargs参数
kwargs将获得一个dict,注意kwargs获得的dict是extra的一份拷贝,对kwargs的改动不会影响到函数外的extra
'''
# name: Harry age: 24 info: {'city': 'DaLian', 'job': 'Engineer'}
extra = {'city': 'DaLian', 'job': 'Engineer'}
person('Harry', 24, **extra)
注意
**kwargs是关键字参数,kwargs接收的是一个字典dict
使用**kwargs是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法