10、形参和实参

文章目录

    • 一、形参和实参介绍
    • 二、形参和实参的具体使用(定义阶段,调用阶段)
        • 2.1 位置参数
        • 2.2 关键字(实)参数
        • 2.3 默认(行)参数
        • 2.4 可变长度的参数(\*与\*\*)
          • 2.4.1 可变长度的位置参数
          • 2.4.2 可变长度的关键字参数
        • 2.5 \*和\**混合使用
        • 2.6 重点知识点
        • 2.7 命名关键字参数(了解)
        • 2.8 混合使用
    • 三、一种特殊的用法

一、形参和实参介绍

  1、形参:在定义函数阶段定义的参数, 叫形式参数, 简称形参(相当于变量名)
  2、实参:再调用函数的阶段传入的值, 叫实际参数, 简称实参(相当于变量值)
  3、关系:在调用的时候实参的值会绑定给形参, 这种绑定关系只能在函数体内使用
  4、实参和形参的绑定关系只有在函数调用时生效, 调用函数结束后接触绑定关系
  5、实参实际是一个值,可以是什么形式?如下:

def func(x, y): # 形参
	return x, y
func(2, 4) # 实参
# 形式一
func(2, 4)
# 形式二
a = 2
b = 4
func(a, b)
# 形式三
func(int('2'), 4)
# 形式四
func(func(2, 3), func(3, 4))

二、形参和实参的具体使用(定义阶段,调用阶段)

2.1 位置参数

按照从左到右的顺序依次定义的参数是位置参数

  • 位置形参: 在函数定义阶段,按照从左到右的顺序依次被定义的‘形参’
      特点:必须被传值,多一个不行少一个也不行
def func(x, y):
	print(x, y)
  • 位置实参: 在函数使用阶段,按照从左到右的顺序依次传入的值
      特点:按照顺序与形参一一对应
func(1, 2)

2.2 关键字(实)参数

  • 关键字实参: 在函数定义阶段,按照key=value的格式传入的
      特点: 指名道姓给某个形参传值, 可以不参照顺序
def func(x, y):
	print(x, y)
func(x=1, y=2)
func(y=2, x=1)

2.3 默认(行)参数

  • 默认形参: 在定义阶段就已经被赋值的,称之为默认参数
      特点:意味着在调用阶段可以不赋值
def func(x, y=2):
	print (x, y)
func(3)
func(x=3, y=4)

2.4 可变长度的参数(*与**)

可变长度: 在调用函数时,传入的(实参)值不固定个数, 而实参是为了形参赋值的, 所以对应着,针对溢出的实参必须有对应的形参来接收

  • 溢出的可能是位置实参或者关键字实参
2.4.1 可变长度的位置参数
  • 用来接收溢出的位置实参(*),溢出的位置实参会被星转化为元组的形式, 然后赋值给紧跟其后的形参名字(一般会跟着args, 即(*args))
# 一、* 用在形参中
def func(x, y, *args):
	print(x, y, args)
func(1, 2, 3, 4, 5, 6)
# 结果
# 1 2 (3, 4, 5, 6)
# 二、* 用在实参中(实参中带*,先将*后的值打散)
def func(x, y, z):
	print(x, y, z)
func(*[11, 22, 33])
# 三、*用在形参和实参上
def func(x, y, *args):
	print(x, y, args)
func(1, 2, [3, 4, 5]) # 结果1 2 ([3, 4, 5],)
func(1, 2, *[3, 4, 5]) # 结果1 2 (3, 4, 5)
2.4.2 可变长度的关键字参数
  • 用来接收溢出的关键字实参(),会将溢出的关键字实参保存成字典的格式,赋值给紧随其后的参数名字(一般会跟着kwargs**, 即(**kwargs))
# 一、** 用在形参中
def func(x, y, **kwargs):
	print(x, y, kwargs)
func(x=1, y=2, z=3, m=5, n=6)
# 结果 1 2 {'z': 3, 'm': 5, 'n': 6}
# 二、** 用在实参中(实参中带*,先将*后的值打散成关键字实参)
def func(x, y, z):
	print(x, y, z)
func(**{'x':1, 'y':2, 'z':3}) # 结果:1 2 3
# 三、**用在形参和实参上
def func(x, y, **kwargs):
	print(x, y, kwargs)
func(**{'x':1, 'y':2, 'z':3, 'm':5}) # 结果:1 2 {'z': 3, 'm': 5}

2.5 *和**混合使用

  • *args必须在**kwargs左边
def func(*args, **kwargs):
	print(args, kwargs)
func(1,2,3,x=1,y=2)# 结果:(1,2,3){'x': 1, 'y': 2}

2.6 重点知识点

  • 位置实参必须放在关键字实参之前
func(x=1,2)# 错的
func(1, y=1)# 对的
  • 可以混合使用,不能为同一个形参重复传值
func(1, y=2, x=1) # 错的
func(1, 2,y=2, x=1) # 错的
  • 位置形参必须在默认形参左边
  • 默认参数的值在定义阶段被赋值, 被赋予的是值的内存地址
  • 虽然默认值可以可以是任意类型, 但是不推荐为可变类型
# 示范一
# 定义阶段
m = 2
def func(x, y=m): # y是2的内存地址
	print(x, y)
# 调用阶段
m=3333
func(1) # 结果1, 2

# 示范二
m = [1]
def func(x, y):
	print(x, y)

# 调用阶段
m.append(2)
func(1) # 结果1,[1,2]
  • 什么时候要位置, 什么时候要默默认:每次调用都需要一个新的值, 用位置形参, 如果大多数调用都不需要新值, 就定义为默认。
  • 函数的调用只跟函数本身有关, 不受外界代码影响
def func(x, l=None):
	if l is None:
		l=[]
	l.append(x)
	return l

func(2)
func(2, [1,2,3])

2.7 命名关键字参数(了解)

  • 在定义函数时, *后定义的参数
  • 特点:1、命名关键字参数必须按照key=value的形式传值
  • 应用场景:在定义函数的时候必须要按照key=value的形式传值
# 特点1
def func(x, y, *, a, b):  # 其中a、b就是命名关键字参数
    print(x, y)
    print(a, b)

func(1, 2, 11, 22) # 错误
func(1, 2, a=11, b=22) # 正确

2.8 混合使用

  • 形参
  • 如果全部使用的顺序应该是:位置参数,默认参数,*args, 命名关键字形参, **kwargs
  • 没有应用场景
def func(x, y=11, *args, z, **kwargs):
	print(x, y, args, z, kwargs)
  • 实参
  • 如果全部使用的顺序应该是:位置,关键字
def func(x, y, z, a, b, c):
	print(x)
	print(y)
	print(z)
	print(a)
	print(b)
	print(c)
func(1, y=2, *(1, 2), **{'b': 11, 'c':22}) # 错误
func(1, *(1, 2), a=2, **{'b': 11, 'c':22}) # 正确

三、一种特殊的用法

def index_(x, y):
	print(x, y)

def wrapper(*args, **kwargs): # args=(1,) kwargs={'y': 2}
	index(*args, **kwargs) # 原封不动的将wrapper传入index_
	# index_(*(1,), **{'y':2})
	# index_(1, y=2)

wrapper(1, y=2) # 根据index_来变

相关连接(笔记来自于视频课程的归类整理):
[1]: https://www.bilibili.com/video/BV1QE41147hU?p=17
[2]: https://www.zhihu.com/column/c_1189883314197168128

你可能感兴趣的:(python全栈学习分享,python,数据结构)