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