函数形参与实参*与**
1.什么是函数
实现某个功能的代码的集合体
2.为什么需要函数
代码结构不清晰,可读性差
冗余度高
扩展性差,可维护性差
3.定义函数
def 函数名(参数1,...,参数n)
'''
函数的相关信息,称为文档注释
'''
函数功能的具体实现代码
return 值
可选:注释 return 参数,(函数体可以用pass来代替)
函数的三种分类
1.有参函数
当函数的函数体执行过程中需要外部数据参与运算,才能完成功能时,就定义为有参
2.无参函数
当函数的函数体执行过程中不需要任何外部数据参与运算,就定义为无参
3.空函数
函数中不包含函数体就称之为空函数
调用空函数是没有任何意义的,主要是用在编写代码的初期,用于定义程序的结构
4.调用函数
函数名加括号
print(函数名()) #打印返回值
print(函数名) #函数的内存地址
函数名() * 10 #在表达式中调用函数
5.函数的返回值
可以一次性return 多个值
什么用返回值:当调用者需要拿到一个明确的结果时
不写return 返回一个None
return 返回一个None
函数执行过程中 一旦遇到return 立马返回,后续代码都不执行
当一次性返回值是多个值时 会自动把这些值打包到元组中
可以直接队函数的返回值金星解压赋值
定义阶段
1.申请内存空间,将函数体的代码存储到内存中
2.将函数的内存地址。与函数名进行绑定
定义阶段不会立即执行函数体的代码,但是会检测语法
调用阶段
1.通过函数名找到函数的内存地址
2.加括号触发函数体的执行
----------------------------------------------------------
函数参数详解
形参与实参
形参即形式参数,就是在定义函数时,括号中指定的参数,本质就是一个名字
例如:
def func1(a,b) #a,b就是形式参数 a=1,b=2
print(a)
print(b)
func1(1,2) #1,2就是实参
实参即实际参数,指的是在调用函数的时候传入的参数,是一个实际的值
在调用函数时就会自动把形参(变量名)和实参(值)进行绑定,
在函数调用结束之后绑定关系就解除了
位置参数(用的最多)
'''
根据调用阶段,参数分为两类 形参和实参
所以对应的位置参数也有两种:
位置形参
位置实参
位置,指的是顺序,从左往右来定义的参数就是位置(顺序)参数
需要注意的是:
只要是定义了的位置形参都必须被传值
位置形参的数量与位置实参的数量必须一致,不能多传,也不能少传
实参会按照传入的位置依次赋值给形参
'''
def func(a,b,c): #abc都是位置形参
print(a,b,c)
func(1,2,3) #1,2,3都是位置实参
def register(name,password,sex):
print("my name is %s pwd:%s sex:%s" % (name,password, sex))
register("virgil","123","man")
关键字参数
关键字实参
在调用函数时,指名道姓的为形参赋值就称之为关键字参数
其优点是:
可以打破传入参数的顺序,可以不与形参顺序相同
注意:
1.不管以什么样的方式传值,每一个形参都必须被传值
2.关键字参数必须位于位置参数的后面
3.不能为同一个参数传多次值
4.使用关键字传参时,实参的名字必须与形参的名字匹配
到底是位置参数还是关键字参数 由实参决定
'''
def func(a,b,c)
print(a)
print(b)
print(c)
func(1,2,c = 3) #与位置参数没有区别
func(c = 3,1,2) #语法错误 关键字参数出现在了位置参数的前面
func(c = 3,a = 1,b = 2) #可以打破位置参数的顺序限制
'''
注册功能:
def register(name,pwd)
print("name is",name)
print("password is",pwd)
register(pwd = '123',name = 'virgil')
'''
默认形参
在定义时,就已经为形参指定了一个值,那这个形参就称之为默认形参
特点:
在调用是可以不用为默认形参传值,使用这个参数时就是默认值
当然也可以传值,这样的话内部使用的就是你传入的值
场景:
当函数中的某一形参经常出现重复的值时,就可以将其定义为默认形参,
可以简化调用代码
需要注意:
1.默认形参必须放在非默认形参的后面
2.默认形参的值在定义时就已经固定了
3.不应该将默认形参的默认值设置为一个可变类型
会导致 每次函数调用都会共用同一个默认参数,我们应该将函数设计为独立的功能,每次调用互不干扰
只能是 int float str tuple
'''
def reg(name,age,sex="woman"):
print(name,age,sex)
res("rose",18)
res("lady",22)
res("Trish",26)
---------------------
def regl(name,sex,hobby):
print(name,sex)
print(hobby)
regl('virgil','man','sport')
regl('Dante','man','play')
可变长参数(重难点)
'''
可变长参数指的是,可以传任意个数的实参
传入实参是为了给形参来使用,意味着必须让形参也具备可以接受任意个数的实参的能力
也就是*和**
带*的形参
带*的形参表示可以接收任意个数的实参,接收到的实参会被打包成元组类型
形参的名字可以随意,但建议用args 是arguments的缩写
带*的实参
在实参前面加*,会自动将*后的值,打散("abc"打散成了"a","b","c")
带*的形参不能接收关键字实参
位置形参与 可变长形参混合使用
当可变长形参出现在了位置形参的前面时,那么后面的位置形参必须以关键字实参来传入
当可变长形参出现在位置形参后面,会先按照顺序给前面的位置形参赋值,最后剩余的就赋值给可变长args
**的使用
形参中如果带有**,会把关键字实参打包成字典类型传入
只能接收多出来的关键字实参
实参中带**,会把**后的字典(也必须是字典类型)打散成关键字实参(**{"a":1})打散为 a=1
* 和 **可以为函数预留扩展空间,后期可以根据需求增加参数,而且旧的函数调用方式也不会出现问题
简单地来说就是提高函数的扩展性
'''
def func(*args):
func(1)
func(1,2)
func(1,2,3)
def func(a,b,c)
print(a,b,c)
func(1,2,*3) #*会将后面的字符串里面的数据打散
# iterable 可迭代的,只要是可以被for in 循环用的都是可迭代的 字符串 列表 元组 字符串 集合
def func(*args,a,b)
print(a,b,args)
func(1,2,3,a=4,b=5)
先为前面的位置形参赋值,后面的多余的关键字参数赋值给**
**不能接收位置实参
def func (a,c,**b):
func(a = 100 , s = 100 , c = 'abc') #结果 1 abc {'s' : 100}
def func(a=1,b=2,**kwargs)
print(a,b,kwargs)
func(a = -1 , b = -2 , s= 10)
实参中带**
def func(name,sex):
print(name,sex)
func(**{"name":"virgil","sex":"man"}) # func(name = "virgil")
# 写一个带有可变长的位置形参函数
def func(name,pwd,**kwargs):
if name == 'virgil' and pwd == '123' and:
if 'phone' in kwargs:
if ukwargs['phone'] == '110':
print('登录成功!')
else:
print('请传入手机号验证!')
print('登录成功!')
else:
print('登录失败!')
func('virgil','123',phone = '110')
该方式可以接受任意个数的位置实参和关键字实参但要注意顺序,位置实参必须在关键字之前
def inner(name,sex,age)
print(name,sex,age)
def outer(*args,*kwargs):
print(args)
print(kwargs)
inner(*args,**kwargs) #inner(1,2,3,100,a=10,b=20)
outer(1,2,3,100,a=10,b=20)
#上述写法 可以将outer接收到的所有参数 原模原样的传给inner函数


浙公网安备 33010602011771号