形参和实参
形参只有在调用时才分配内存,调用结束时即刻释放所分配的内存单元,因此形参只在函数内部有效。
实参可以是常量,变量,表达式,函数等,必须有确定的值。
位置参数
调用函数时,依照位次赋值。
def func(x, y): # 函数名小写(比较规范)形参
print(x**y)
func(1, 2) # 1
func(2, 1) # 2
默认参数
特点
函数调用时,传入参数的值比较固定可以设置成默认参数。
- 函数定义时,默认参数在位置参数之后,
- 默认参数必须指向不变对象!!
- 调用时不用赋值,默认参数赋值修改原来值。
def func(x, y=2):
print(x**y)
func(2) # 4
func(2, 3) # 8
默认参数必须指向不变对象
def func(l=[]):
l.append('小明')
print(l)
func([1,2,3,4])
# [1, 2, 3, 4, '小明']
func([1,2])
# [1, 2, '小明']
func()
# ['小明']
func()
# ['小明', '小明']
func()
# ['小明', '小明', '小明']
函数在定义的时候,默认参数L也是一个变量,l默认指向空列表[ ],此时空列表是没有元素的。调用参数赋值时,l指向了其他的列表,函数调用正常。如果没有赋值,l一直指向空列表[ ],空列表作为容器,调用一次增加一个元素,不再是函数定义时的[ ]列表了。
def func(l=None):
l=[]
l.append('小明')
# return l # 返回结果,不打印
print(l)
func()
func()
# ['小明']
# ['小明']
关键参数
函数调用传入参数值要按顺序,如果不按照顺序,传参时可以使用关键参数。
- 调用时,关键参数要放在位置参数之后
def register(name, age, city):
print("""
name: %s
age: %s
city: %s
""" % (name, age, city))
register('小明',22,'北京')
register('小明',city='北京',age=22) # 关键参数放在位置参数之后
register(city='北京','小明',age=22) # 报错
关键字参数最大的优点在于,可以指定默认值,给参数指定默认值后,调用函数时可不提供它!可以根据需要,一个参数值也不提供、提供部分参数值或提供全部参数值。
def hello(name='小明', city='北京'):
print('欢迎来自{}的{}'.format(city, name))
hello()
# 不提供
# 欢迎来自北京的小明
hello('小强')
# 按顺序提供部分或全部
# 欢迎来自北京的小强
hello('济南')
# 不按顺序提供需要使用关键字参数
# 欢迎来自北京的济南
hello(city='济南')
# 欢迎来自济南的小明
hello(city='上海',name='小红')
# 欢迎来自上海的小红
非固定参数 *args
**kwargs
在不确定传入多少参数时,可以在定义函数时,形参设置为非固定参数。
*args
- 把多传入的参数变成元祖形式
- 如果传入值是列表或者元祖形式加*号
- *args在定义函数时,如果后面还有参数,则调用时注意用关键字传参
def re(name, *args):
print('姓名:', name)
print('其他信息:', args)
re('小明', 22, '北京')
# 姓名: 小明
# 其他信息: (22, '北京')
def su(*args):
print(args)
print(sum(args))
num=[1,2,3]
# su(num)
# args把num又变成元祖形式([1, 2, 3],)报错,
# 如果传入值是列表形式加*号
su(*num)
# (1, 2, 3)
# 6
def hello(name, *n, city):
print('hello', name, 'from', city, n)
# hello('xiaoming', 181,54,'shanghai')报错
hello('xiaoming', 181, 54, city='shanghai')
# hello xiaoming from shanghai (181, 54)
# 有个细小的差别
def hello(name, *n, city):
print('hello', name, 'from', city, *n)
# hello xiaoming from shanghai 181 54
**kwargs
特点
- 接收的是未设置形参名的关键参数,调用时如果不用关键参数赋值,会将参数值传入args组成元祖形式
- 把输入值转成字典形式
- 传入参数值为字典格式,同样要加**号,不加会传入args。
def re(name, *args, **kwargs):
print('姓名:', name)
print('其他信息:', args)
print('其他信息:', kwargs)
re('小明', 22, '北京', school='北大')
# 姓名: 小明
# 其他信息: (22, '北京')
# 其他信息: {'school': '北大'}
re('小明', 22, '北京', {'school':'北大'}) # 不加**号
# 姓名: 小明
# 其他信息: (22, '北京', {'school': '北大'}) # 元祖
# 其他信息: {}
re('小明', 22, '北京', **{'school':'北大'}) # 加**号
# 姓名: 小明
# 其他信息: (22, '北京')
# 其他信息: {'school': '北大'}
限制命名关键字参数
限制命名关键字参数,调用函数时,必须传入函数要求的关键字参数。
- 如果函数定义中没有可变参数args,需要 * 作为分隔符
- 如果有可变参数,不需要分隔符
- 调用函数传参时依然需要用关键字参数形式
def re(name, *,age,city): # 限制必须而且只能传入 age=,city=
print('姓名:', name)
print('其他信息:', age,city)
# re('小明',age=22,city='北京',school='北大') # 报错
re('小明',age=22,city='北京')
# 姓名: 小明
# 其他信息: 22 北京
# re('小明',age=22)
# re() missing 1 required keyword-only argument: 'city'
def re(name, *args,age,city): # 限制必须且只能传入age=,city=
print('姓名:', name)
print('其他信息:', args)
print('限制多余信息:',age,city)
re('小明','180cm',age=22,city='北京')
# 姓名: 小明
# 其他信息: ('180cm',)
# 限制多余信息: 22 北京