提示:上一篇文章介绍了Python中函数的基本使用,本篇文章主要说明一下Python函数实参的传递方式

位置参数:调用函数时根据函数定义的参数位置来传递参数。

  1. def user_info(name, age, gender):
  2. print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
  3. # 调用函数
  4. user_info('TOM', 20, '男')

注意:传递和定义参数的顺序及个数必须一致。就是将对应位置的实参复制给对应位置的形参,第一个实参赋值给第一个形参,第二个实参赋值给第二个形参,以此类推。

示例

  1. def user_info(name, age, gender):
  2. print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
  3. # 1.调用函数,传递的参数个数不正确
  4. # 结果:TypeError: user_info() missing 1 required positional argument: 'gender'
  5. user_info('TOM', 20)
  6. # 2.调用函数,传递的参数的顺序不正确
  7. # 不会报错,但输出的内容完全歧义。
  8. # 结果:您的名字是男, 年龄是TOM, 性别是20
  9. user_info('男', 'TOM', 20)

可以不按照形参定义的顺序去传递,而直接根据参数名去传递参数。

函数调用,通过键=值形式加以指定。

可以让函数更加清晰、容易使用,同时也清除了参数的需求。

  1. def user_info(name, age, gender):
  2. print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
  3. # 正确用法
  4. user_info('Rose', age=20, gender='女')
  5. user_info('小明', gender='男', age=16)
  6. # 位置参数必须写在关键字参数的前面
  7. # 结果:SyntaxError: positional argument follows keyword argument
  8. user_info(gender='男', age=16, "孙悟空")
  9. # 位置参数必须写在关键字参数的前面,同时位置参数的顺序也要对应
  10. # 结果:TypeError: user_info() got multiple values for argument 'age'
  11. user_info("孙悟空", '男', age=16)
  12. # 格式正确,但是位置参数的顺序不正确,结果也会产生歧义。
  13. # 结果:您的名字是20, 年龄是孙悟空, 性别是男
  14. user_info(20, "孙悟空", gender='男')
  15. """
  16. 总结:定义参数时,位置参数和关键字参数,尽量统一使用一种。
  17. """

注意:

  • 位置参数和关键字参数可以混合使用。
  • 函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。

缺省参数也叫默认参数,用于定义函数时,为参数提供默认值,调用函数时可不传该默认参数的值。

提示:所有位置参数必须出现在默认参数前(因为默认参数的格式和关键字参数格式一样,所以都要写在所有参数之后),包括函数定义和调用。

  1. def user_info(name, age, gender='男'):
  2. print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
  3. # 没有为缺省参数传值,表示使用默认值。
  4. user_info('TOM', 20)
  5. # 为缺省参数传值,使用这个值,即修改了默认值。
  6. user_info('Rose', 18, '女')

注意:函数调用时,如果为缺省参数传值则修改默认参数值,否则使用这个默认值。

不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。

  1. """
  2. 1.在定义函数时,可以在形参前边加上一个*,这样这个形参将会获取到所有的实参,
  3. 它将会将所有的实参保存到一个元组中
  4. 2.*args说明:*一定要写,args表示形参,可以自定义名称。
  5. 但在实际工作中,一般默认使用*args做为不定长包裹位置传递参数的表示,不做修改。
  6. """
  7. def user_info(*args):
  8. print(args)
  9. # ('TOM',)
  10. user_info('TOM')
  11. # ('TOM', 18)
  12. user_info('TOM', 18)
  13. # ()
  14. user_info()

注意:传进的所有参数都会被args变量收集,它会根据传进的所有的位置实参,合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。(这个过程也叫装包或者组包)

小应用

  1. # 定义一个函数,可以求任意个数字的和
  2. def sum(*nums):
  3. # 定义一个变量,来保存结果
  4. result = 0
  5. # 遍历元组,并将元组中的数进行累加
  6. for n in nums:
  7. result += n
  8. print(result)
  9. sum(123, 456, 789, 10, 20, 30, 40)

注意事项

  1. # 注意事项1
  2. # 带星号的形参只能有一个
  3. # 带星号的参数,可以和其他参数配合使用
  4. # 第一个参数给a,第二个参数给b,剩下的都保存到c的元组中
  5. def fn2(a, b, *c):
  6. print('a =', a)
  7. print('b =', b)
  8. print('c =', c)
  9. fn2(1, 2, 3, 4, 5)
  10. """
  11. 输出结果:
  12. a = 1
  13. b = 2
  14. c = (3, 4, 5)
  15. """
  16. # 注意事项2
  17. # 可变参数不是必须写在最后,但是注意,
  18. # 带*的参数后的所有参数,必须以关键字参数的形式传递
  19. # 第一个参数给a,剩下的位置参数给b的元组,c必须使用关键字参数
  20. def fn2(a, *b, c):
  21. print('a =', a)
  22. print('b =', b)
  23. print('c =', c)
  24. # TypeError: fn2() missing 1 required keyword-only argument: 'c'
  25. # fn2(1, 2, 3, 4, 5) # 报错
  26. fn2(1, 2, 3, 4, c=5)
  27. """
  28. 输出结果:
  29. a = 1
  30. b = (2, 3, 4)
  31. c = 5
  32. """
  33. # 注意事项3
  34. # 所有的位置参数都给a,b和c必须使用关键字参数,
  35. # 且必须写在最后。
  36. def fn2(*a, b, c):
  37. print('a =', a)
  38. print('b =', b)
  39. print('c =', c)
  40. fn2(1, 2, 3, b=4, c=5)
  41. """
  42. 输出结果:
  43. a = (1, 2, 3)
  44. b = 4
  45. c = 5
  46. """
  47. # 注意事项4
  48. # 如果在形参的开头直接写一个*,
  49. # 则要求我们的所有的参数必须以关键字参数的形式传递。
  50. def fn2(*, a, b, c):
  51. print('a =', a)
  52. print('b =', b)
  53. print('c =', c)
  54. fn2(a=3, b=4, c=5)
  55. """
  56. 输出结果:
  57. a = 3
  58. b = 4
  59. c = 5
  60. """
  61. # 注意事项5
  62. # *形参只能接收位置参数,而不能接收关键字参数
  63. def fn3(*a):
  64. print('a =', a)
  65. # TypeError: fn3() got an unexpected keyword argument 'a'
  66. fn3(a=3, b=4, c=5)
  1. """
  2. **kwargs说明:**一定要写,args表示形参,可以自定义名称。
  3. 但在实际工作中,一般默认使用**kwargs做为不定长包裹关键字传递参数的表示,不做修改。
  4. """
  5. # 收集所有关键字参数,它会将这些参数统一保存到一个字典中返回。
  6. # 字典的key就是参数的名字,字典的value就是参数的值
  7. def user_info(**kwargs):
  8. print(kwargs)
  9. # {'name': 'TOM', 'age': 18, 'id': 110}
  10. # 关键字不能加引号,应为关键字对应的是形参。
  11. user_info(name='TOM', age=18, id=110)
  12. # 包裹关键字传递只能有一个,并且必须写在所有参数的最后
  13. # 实参可以不按顺序传递
  14. def fn3(b, c, **a):
  15. print('a =', a, type(a))
  16. print('b =', b)
  17. print('c =', c)
  18. fn3(e=10, b=1, d=2, c=3, f=20)
  19. """
  20. 输出结果:
  21. a = {'e': 10, 'd': 2, 'f': 20} <class 'dict'>
  22. b = 1
  23. c = 3
  24. """

综上:无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程(组包简单的说,就是收集分散的参数,返回一个整体数据)。关于组包对应就是拆包,在之前的文章【Python元组】中有介绍,可以对应的查看。

参数定义与调用顺序的基本原则是:位置参数,默认参数,包裹位置,包裹关键字。(定义和调用都应遵循)

提示:默认参数与包裹位置参数可以根据需求进行位置调换。

  1. def user_info(name, age, sex=1, *args, **kargs):
  2. print name, age, sex, args, kargs
  3. user_info('tanggu', 25, 2, 'music', 'sport', class=2)
  4. # 输出结果
  5. # tanggu 25 1 ('music', 'sport') {'class'=2}

关于组包对应就是拆包,在之前的文章【Python元组】中有介绍,可以对应的查看。

(1)通过包裹位置对一个元组进行解包

操作方式:使用*号。

如下示例:

  1. # 参数的解包(拆包)
  2. def fn4(a, b, c):
  3. print('a =', a)
  4. print('b =', b)
  5. print('c =', c)
  6. # 创建一个元组
  7. t = (10, 20, 30)
  8. # 我们直接传递t,会报错
  9. # TypeError: fn4() missing 2 required positional arguments: 'b' and 'c'
  10. # fn4(t)
  11. # 而以前我们是这样拆包的
  12. # fn4(t[0], t[1], t[2])
  13. """
  14. 输出结果:
  15. a = 10
  16. b = 20
  17. c = 30
  18. """
  19. # *号拆包
  20. # 传递实参时,也可以在序列类型的参数前添加星号,
  21. # #这样他会自动将序列中的元素依次作为参数传递。
  22. # 这里要求序列中元素的个数必须和形参的个数的一致
  23. fn4(*t)
  24. """
  25. 输出结果:
  26. a = 10
  27. b = 20
  28. c = 30
  29. """

(2)通过包裹关键字对一个字典进行解包

操作方式:使用**号。

如下示例:

  1. # 参数的解包(拆包)
  2. def fn4(a, b, c):
  3. print('a =', a)
  4. print('b =', b)
  5. print('c =', c)
  6. # 创建一个字典
  7. d = {'a': 100, 'b': 200, 'c': 300}
  8. # 通过 **来对一个字典进行解包操作
  9. # 字典中的key要和函数的形参一一对应。
  10. fn4(**d)
  11. """
  12. 输出结果:
  13. a = 100
  14. b = 200
  15. c = 300
  16. """

版权声明:本文为liuyuelinfighting原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/liuyuelinfighting/p/15002474.html