函数(def)
一、函数的概述和意义
1. 概述
函数描述的是生活中的一种行为,如吃饭的行为。在程序中声明一个函数,就相当于生活中学习一个行为。
函数声明完不会立即执行,比如吃饭这个行为虽然具备,但并非是立即执行的。
循环和函数都可以简化代码,使代码更加简洁。但是循环做的事不能独立分开,所以需要函数来解决重复事情中断问题。依旧以吃饭为例,一日三餐,但是这三餐并不是一起吃的,在这中间还会做其他不同的事情,此时循环就显得有些无力了。
2.定义
函数就是实现特定功能,能够重复使用的代码块(一行或多行)。
3.意义
函数能提高应用的模块性和代码的复用率。
二、函数的声明和调用
1. 函数的声明
# 定义函数的格式
def 函数名([参数1,参数2...]):
"""文档注释:简要描述函数实现的功能"""
实现功能的代码
[return 返回的数据]
# 调用函数
函数名([参数1,参数2...])
说明:
- def : define ,用于声明一个函数
- 函数名:标识符,符合标识符的规则和规范。(由数字字母下划线组成,数字不能开头,不能使用关键字)
- []:表示可选内容
- 参数:函数需要外界输入一些依赖的数据,参数可以没有或有一个或多个
形参:形式上的参数,函数如果要执行,形式上需要参数数据,在定义函数时声明在函数后面的括号中。
实参:实际上的参数,函数调用时真正使用的数据为实参。 - 默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。
- return:关键字,用于将函数内的数据返回到函数外。不带表达式的return相当于返回None。
def print_hello():
"""打印hello world"""
print("hello world")
# 调用函数
print_hello()
2. 函数的调用
- 函数的调用:函数名()
- 函数必须先定义后调用
- 函数不调用不会执行
- 函数只需要定义一次,就可以调用任意次
- 多次调用函数,不同的调用过程互相独立的!不会互相影响。
# 函数的调用
def eat():
"""吃饭"""
print("该吃饭了")
e = eat # 将函数eat赋值给e,此时的e就是eat函数
eat() # 调用 该吃饭了
e() # 调用 该吃饭了
print(e) # 打印eat这个函数地址 <function eat at 0x0000020820F43B88>
print(eat) # 打印eat这个函数地址 <function eat at 0x0000020820F43B88>
print(eat()) # 该吃饭了 None (先调用一遍函数,然后打印)
a = eat() # 将eat函数的返回值赋值给a
# a() # 报错。因为a接受的是eat函数的返回值,并非是一个函数
三、函数的参数
1.位置参数
实参传递的顺序必须按照形参定义的顺序进行传递的传参方式。
# def add(num1, num2:int): # :数据类型 可明确定义数据类型
def add(num1, num2):
"""求两数之和"""
res = num1+num2
print(res)
add(9, 14) #23
2. 关键字参数(函数调用时)
忽略了原本的位置关系,明确指出形参和实参的对应关系。
- 格式:函数名(形参=实参)
- 优点:
参数传递更加明确,哪个数据是传给哪个形参的。
可读性提升,调用时明确的通过形参知道实参意义。 - 注意:关键字参数和位置参数同时使用时,关键字参数必须在位置参数后面定义。
# 需求定义一个函数,给定两个数字,遍历两个数字之间的所有数字
def func2(num1,num2):
"""打印num1到num2之间的数字"""
for i in range(num1,num2+1):
print(i)
# 关键字参数
func2(num1=10,num2=100)
func2(num2=100,num1=10)
3. 默认参数(定义函数提现)
在定义函数时,可以对某些形参设定默认值,有默认值的参数,在调用时可以不传入,如果不传入就使用默认值。优先使用传入的值。
- 使用场景:某个参数变化比较小,就可以指定一个默认值。
- 默认值参数要放在常规参数的后面。
def printinfo(name, age=20):
"""打印个人信息"""
print(f"姓名:{name},年龄:{age}")
# 调用
printinfo(name="峥嵘") # 姓名:峥嵘,年龄:20
printinfo("zr", age=18) # 姓名:zr,年龄:18
4. 不定长参数(*args,**kwargs)
在定义函数时,在形参前加入*或者**来使函数变成元组或字典。
-
适用场景:在定义函数时,函数参数有很多个或者不确定参数的数量。
-
不定长参数接收到的参数只会作为参数的元素,而不是一个独立的参数。
如果没有接收到参数,则返回一个具体的空类型(()或{})。 -
可变参数:*args —— 多个参数
可变关键字参数:***kwargs —— 多个key:value参数 -
注意:**kwargs必须放在*args后面
4.1 元组类型可变参数(*args):只能通过位置参数传递
def print_info2(*args):
"""介绍个人信息"""
print(args)
for i in args:
print(i)
# 不善言辞
print_info2()
# 正常
print_info2('zs',20,180)
print_info2(name='zs', age=20, height = 180) # 错误,不能使用关键字方式传递
# 健谈
print_info2('ls',20,175,70,"郑州","吃")
# 定义元组
t = (1,4,5,6,7,8,8,9,9,0,0)
print_info2(t) # 传入一个元素:把元组当做一个整体
print_info2(*t) # 传入多个元素:将元组打散
4.2 字典类型可变关键字参数(**kwargs)
def print_info3(**kwargs):
"""介绍个人信息"""
print(kwargs)
print_info3('zs',20,180) # 错误
print_info3(name='zs', age=20, height = 180) # 正确
5. 强制关键字参数
严格的提高代码的可读性。
defshow(name,*,age,gender,email):
"""
展示用户资料的函数
name是一个普通的位置参数
*分隔符号,后面的都是关键字参数[必须]
"""
print(f"姓名:{name}")
print(f"年龄:{age}")
print(f"性别:{gender}")
print(f"邮箱:{email}")
#函数的调用:形式参数*符号,后面的所有参数~必须按照key=value的方式传递
show("峥嵘",age=18,gender="女",email="1536592208@qq.com"
6.语义上的万能参数
理论上可以接受任意格式的参数。
deftest(*args,**kwargs):
"""
测试函数
*args:接受可变参数
**kwargs:接受可变关键字参数
"""
print(args)
print(kwargs)
'''
函数的定义规范~通常先有位置参数,后面是关键字参数
'''
#0个参数
test()
#1个位置参数
test("name")
#2个位置参数
test("tom","jerry")
#1个位置参数,1个关键字参数
test("tom",friend="jerry")
#特殊:首先是违反了规范,万能参数不接受这样的参数
test(name="tom",18)
总结:
- 在定义函数时:位置参数-- 默认参数和*args–**kwargs
- 在调用函数时:位置参数—关键字参数
四、函数的返回值
函数的返回值:函数作为一种行为,返回值就是行为执行的结果。
- return:关键字,用来将数据返回给调用者。
- 如果需要返回值
- return只能出现在函数中。一旦执行,函数立即结束!
1. 没有返回值
如果没有返回值或是return后无任何数据,那么默认返回None
def func():
"""没有返回值"""
return
print(func()) # None
2. 返回单个数据
def func1():
"""返回值为单个数据"""
return “python”
print(func1()) # “python”
3. 返回一组数据
def func2():
"""返回值是一组数据"""
return ['python', 'java', 'php', 'c#']
print(func2) # ['python', 'java', 'php', 'c#']
4. 返回多个数据
返回的数据类型是元组。
def func3():
return 'hello', 1,1.3,[5,6],(7,),{'a','b','c'},{'name':'zs'}
print(func3()) # ('hello', 1, 1.3, [5, 6], (7,), {'c', 'b', 'a'}, {'name': 'zs'})
5. return作用
- 将函数内的数据返回到函数外
- 用于结束一个函数的执行
五、函数的相互调用
def f1():
print('f1')
def f2():
print("f2")
f1()
f2()
六、递归函数
如果一个函数在内部调用它自己,这个函数就是递归函数。
使用递归函数的条件
- 必须留出口
- 自己调用自己
def print_num(num):
"""使用递归函数向控制台打印3,2,1"""
if num == 0:
return # 结束函数
print(num)
num -= 1
print_num(num)
print("*************")
print_num(3)