函数与参数
# 函数的介绍
# 介绍
函数是存放功能(一堆代码)的容器,定义好一函数之后,可以重复的调用这个功能。
函数一定是先定义,然后才能调用,不定义函数直接调用,相当于在引用一个不存在的变量名。
可以解决重复代码的冗余问题。
# 函数的分类
内置函数
自定义函数
# 函数的使用过程
# 定义阶段
def 函数名():
此阶段只检测语法,不执行代码。
def关键字会申请内存空间将函数体代码存放起来,然后将内存地址绑定给函数名,即函数名=函数的内存地址。
另外函数的命名应该反映出函数的功能。
# 调用函数
函数名()
通过函数名查找函数的内存,加括号会触发函数体代码的运行。
# 函数的定义
# 定义方式
def
: 定义函数的关键字。
函数名
:函数名指向函数内存地址,是对函数体代码的引用。
括号
:括号内定义参数,参数是可有可无的。
冒号
:括号后要加冒号,然后在下一行开始缩进编写函数体的代码。
文档描述
:描述函数功能、参数等信息的文档,非必要,但是建议加上,增强函数的可读性。但也不能太过于冗长。
函数体
:由语句和表达式组成,也就是代码块。
return 值
:定义函数的返回值,也可以不返回值。
def 函数名(参数1,参数2,...):
"""文档描述"""
函数体
return 值
2
3
4
# 函数定义的最理想状态
函数的调用只跟函数本身有关,不会被外界代码影响到结果,可以被预知到调用后的结果。比如函数体内不调用函数之外的变量。
# 定义空函数
先列举出所有功能,并用pass充当函数体。
例如:
def auth_user():
"""user authentication function"""
pass
2
3
# 返回值的三种形式
return是函数结束的标志,函数内可以有多个return,只要执行一个,整个函数就会立刻结束,并且将该return后的值作为本次运行的结果返回。
# None
表示没有return,或者return了None。
# 一个值
return 值
# 多个值
return 值1,值2,值3
会自动将这些值放到一个元组中返回。
# 参数的分类
# 形式参数
形式参数简称形参,是在定义阶段定义的函数所需参数的名称。
在函数内形参实际就是变量名。
# 实际参数
实际参数简称实参,是在调用函数阶段需要传入的值。
函数调用完后会解除实参和形参的绑定,即实参的引用计数会减一。
# 形参的定义
# 位置形参
在函数定义阶段,按从左到右顺序定义形参名。
例如:
def test(a, b):
pass
2
# 默认形参
在定义阶段就会被赋值一次,意味着在调用阶段允许不用为其进行赋值。
默认值可以被指定为任意类型,但不推荐使用可变类型,可能会导致逻辑混乱。
例如:
def test(a, b=1):
pass
2
# 实参的传入
# 位置传参
test(1, 2)
实参位置和形参位置必须对应。
# 关键字传参
test(1, a=2)
可以同时使用位置和关键字传参,但位置参数必须在关键字参数的前面。
# 变量传入
test(a)
# 返回值传入
例如:test(a())
将函数a()
最终的返回值作为参数传入test()
。
# 可变长度参数 *和**
可变长度指的是在调用函数时,传入的实参的个数不固定。
# 可变长位置形参
*args
用于接收溢出的位置实参。
约定俗成使用 args 作为形参名。
例如:
def test(a, *args):
print(args)
test(1, 2, 3, 4, 5)
>> 输出元组 (2,3,4,5)
2
3
4
# 可变长关键字形参
**kwargs
用于接收溢出的关键字实参。
实参必须是 key = value 键值对。
约定俗成使用 kwargs 作为形参名。
例如:
def test(a, **kwargs):
print(kwargs)
print(kwargs['b'])
test(1, b=2, c=3, d=4, e=5)
>> 输出 {'b': 2, 'c': 3, 'd': 4, 'e': 5}
>> 输出 2
2
3
4
5
6
# 解压位置实参
*有序类型
实参中带*的,会将*后面有序类型的元素值,解压成位置实参,然后传给函数。
和位置实参一样要和形参对应。
例如:
def test(a,b,c):
print(a,b,c)
# 同等于test(1,2,3)
test(*[1,2,3])
>> 输出 1 2 3
2
3
4
5
6
# 解压关键字实参
**字典类型
同*实参的不同点在于,**可以将字典解压成键值对。
- 例如:
def test(a,b,c):
print(a,b,c)
# 同等于test(a=1,b=2,c=3)
test(**{'a':1,'b':2,'c':3})
>> 输出 1 2 3
2
3
4
5
6
# *与**混用
*args
必须在 **kwargs
之前。
def test(*args, **kwargs):
调用时也是一样。
test(1,2,3,a=1,b=2,c=3)
# 形参*与实参*同时用
因为传入给可变形参,是以元组或字典的形式,而在调用print时,元组或字典又被*解压出来。
def test(*args,**kwargs):
print(*args,**kwargs)
test(1,2,3,4)
2
3
# 命名关键字参数
# 介绍
在定义函数时,*后定义的形参,传入实参时必须用关键字传入。
# 例如:
def test(a,b,*,c,d):
pass
test(1,2,d=4,c=3)
2
3
# 各类形参组合
位置形参,默认形参,*args
,命名关键字形参,**kwargs
def test(a,b=2,*args,e,**kwargs): ...
# 函数参数提示功能
# 介绍
Python中不能强制设定传入函数的参数的数据类型。
只能通过提示的方式,来提醒函数使用者应该传入哪种类型,但是不提示也问题不大,可以写到函数说明中。
只能做声明,无法强制要求。
# 定义
def func(name1:type,name2:type)->type:
name1:type
声明这个参数应当传入的指定类型。如果要写默认值,要写在:type后面。
例如:
def func(a: int = 123):
->type
声明返回的值是什么类型。
例如:
def func()->int:
可以提示任意字符
例如:
def func(name1:'我是字符串'):
# 查看
print(func.__annotations__)
# 例如
# num:int 声明num应当传入int类型的值。
# ->int 声明返回的值是int类型。
def func(num:int, content:str)->int:
pass
return 1
2
3
4
5