5.2 函数参数
- 一般来说,在函数内部直接修改形参的值不会影响实参,而是创建一个新变量。
def func(a):
print('func: a=',a,id(a))
a=10 #在函数内部修改形参的值
print('modi: a=',a,id(a))
x=5.0
print('main: x=',x,id(x))
func(x)
print('main: x=',x,id(x)) #x的值不随形参的值的改变而改变
main: x= 5.0 1977940378800
func: a= 5.0 1977940378800
modi: a= 10 140707831649376
main: x= 5.0 1977940378800
- 在有些情况下,可以通过特殊的方式在函数内部修改实参的值。
def modify(v): #修改列表元素值
v[0] = v[0] + 1
a = [2]
modify(a)
print(a)
[3]
def modify(v,item): #为列表增加元素
v.append(item)
a = [2]
modify(a,3)
print(a)
[2, 3]
def modify(d): #修改字典元素值或为字典增加元素
d['age'] = 18
a = {'age': 19,'name': 'Xu','sex': 'Male'}
modify(a)
print(a)
{'age': 18, 'name': 'Xu', 'sex': 'Male'}
5.2.1 位置参数
- 调用函数时实参和形参的顺序必须严格一致,且实参和形参的数量必须相同
def demo(a, b, c):
print(a, b, c)
demo(3, 4, 5) #按位置传递参数
demo(3, 5, 4)
demo(1, 2, 3, 4) #实参与形参数量必须相同
3 4 5
3 5 4
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-12-287f594558cd> in <module>
3 demo(3, 4, 5) #按位置传递参数
4 demo(3, 5, 4)
----> 5 demo(1, 2, 3, 4) #实参与形参数量必须相同
TypeError: demo() takes 3 positional arguments but 4 were given
5.2.2 默认值参数
- 任何一个默认值参数右边都不能再出现没有默认值的普通位置参数
def say( message, times = 1):
print(message * times)
say('hello')
say('hello',3)
hello
hellohellohello
- 多次调用函数并且不为默认值参数传递值时,默认值参数只在定义时进行一次解释和初始化
def demo(newitem,old_list = []):
old_list.append(newitem)
return old_list
print(demo('5',[1,2,3,4])) #right
print(demo('aaa',['a','b'])) #right
print(demo('a')) #right
print(demo('b')) #没有进行初始化,old_list的默认值变为'a'
print(demo('b',[]))
[1, 2, 3, 4, '5']
['a', 'b', 'aaa']
['a']
['a', 'b']
['b']
- 解决方法
def demo(newitem,old_list = []):
if old_list == []:
old_list = []
old_list.append(newitem)
return old_list
print(demo('a'))
print(demo('b'))
['a']
['b']
- 可以使用“函数名.defaults”查看所有默认参数的当前值
demo.__defaults__
([],)
- 函数的默认值参数实在函数定义时确定值的
i = 3
def f(n=i): #参数n的值仅取决于i的当前值
print(n)
f()
i = 5 #函数定义后修改i的值不影响参数n的默认值
f()
f.__defaults__ #查看函数默认值参数的当前值
3
3
(3,)
5.2.3 关键参数
- 实参和形参顺序可以不一致
def demo(a,b,c=5):
print(a,b,c)
demo(3,7)
demo(c=8,a=9,b=0)
3 7 5
9 0 8
5.2.4 可变长度参数
- 两种形式:
- *parameter:用来接受多个实参并将其放在一个元组中
- **parameter:接受关键参数并存放到字典中
def demo(*p):
print(p)
demo(1,2,3)
demo(1,2,3,4,5,6,7)
(1, 2, 3)
(1, 2, 3, 4, 5, 6, 7)
def demo(**p):
for item in p.items():
print(item)
demo(x=1,y=2,z=3)
('x', 1)
('y', 2)
('z', 3)
- 几种不同类型的参数可以混合使用,但是不建议这样做
def func_4(a,b,c=4,*aa,**bb):
print(a,b,c)
print(aa)
print(bb)
func_4(1,2,3,4,5,6,7,8,9,xx='1',yy='2',zz=3)
func_4(1,2,3,4,5,6,7,xx='1',yy='2',zz=3)
1 2 3
(4, 5, 6, 7, 8, 9)
{'xx': '1', 'yy': '2', 'zz': 3}
1 2 3
(4, 5, 6, 7)
{'xx': '1', 'yy': '2', 'zz': 3}
5.2.5 传递参数时的序列解包
- 传递参数时,可以通过在实参序列前加一个星号将其解包,然后传递给多个单变量形参。
def demo(a, b, c):
print(a+b+c)
seq = [1, 2, 3]
demo(*seq) #解包后按位置传递
tup = (1, 2, 3)
demo(*tup)
dic = {1:'a', 2:'b', 3:'c'}
demo(*dic)
demo(*dic.values())
Set = {1, 2, 3}
demo(*Set)
6
6
6
abc
6
- 调用函数时如果对实参使用一个星号*进行序列解包,那么这些解包后的实参将会被当作普通位置参数对待,并且会在关键参数和使用两个型号**进行序列解包的参数之前进行处理。
def demo(a,b,c):
print(a,b,c)
demo(a=1,*(2,3))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-13-620ef3ddff35> in <module>
1 def demo(a,b,c):
2 print(a,b,c)
----> 3 demo(a=1,*(2,3))
TypeError: demo() got multiple values for argument 'a'
demo(c=1,*(2,3)) #有限处理a,b
2 3 1
demo(**{'a':1, 'b':2}, *(3,)) #序列解包不能在关键参数解包之后
File "<ipython-input-16-ca9348af944f>", line 1
demo(**{'a':1, 'b':2}, *(3,)) #序列解包不能在关键参数解包之后
^
SyntaxError: iterable argument unpacking follows keyword argument unpacking
demo(*(3,), **{'a':1, 'b':2}) #a=3已被占用
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-18-edb3b6269a99> in <module>
----> 1 demo(*(3,), **{'a':1, 'b':2}) #a=3已被占用
TypeError: demo() got multiple values for argument 'a'
demo(*(3,), **{'c':1, 'b':2})
3 2 1