python基础04-函数
函数
一、函数的基本使用
1. 基本概念
所谓函数,就是把 具有独立功能的代码块 组织为一个整体,在需要的时候 调用
函数的使用包含两个步骤:
- 定义函数 —— 在函数中编写代码,实现功能
- 调用函数 —— 执行编写的代码
函数的作用:
- 提高代码编写效率, 代码重用
- 写一次函数代码块,后面使用的时候,只需要调用函数即可,无需重新编写函数代码块
2. 函数的定义和调用
2.1 函数的定义
定义函数的格式如下:
def 函数名(): 函数内部的代码块 ……
def
是英文define
的缩写- 函数名称的命名应该符合标识符的命名规则
- 可以由 字母、下划线 和 数字 组成
- 不能以数字开头
- 不能与关键字重名
- 建议不要和类型同名
2.2 函数的调用
函数只是定义,不调用不会自动执行,用户看不到没有效果
函数调用的格式:
函数名字()
2.3 第一个函数演练
需求
- 编写一个打招呼
say_hello
的函数,封装三行打招呼的代码 - 在函数下方调用打招呼的代码
示例代码:
""" 步骤流程: 函数定义: 1. def 函数名字(): 2. 函数体,打印信息 函数调用:函数名字() """
函数定义
def say_hello():
print(“hello 1”)
print(“hello 2”)
print(“hello 3”)
print(‘函数调用前’)
say_hello() # 函数调用
print(‘函数调用后’)
运行结果:
```shell
函数调用前
hello 1
hello 2
hello 3
函数调用后
二.函数执行过程、文档注释
1. 函数执行流程
1.1 函数执行流程
- 如果不主动调用函数,函数是不会主动执行的
- 函数调用时,默认往前面找函数的定义,如果没有找到函数定义,则报错:
NameError: name 'say_hello' is not defined
(名称错误:say_hello 这个名字没有被定义)
1.2 Debug 的单步调试
F7 Step Into 可以单步执行代码,如果是函数,会进入函数内部
F8 Step Over 可以单步执行代码,如果函数,直接执行函数,不会进入函数内部
2. 函数的文档注释
在开发中,如果希望给函数添加文档注释,应该在 定义函数 的下方,使用 连续的一对三引号
在 连续的一对三引号 之间编写对函数的说明文字
def func_sum(): """求和 1+2""" add_result = 1 + 2 print(add_result) func_sum()
在 函数调用 位置,使用快捷键
Ctrl + Q
可以查看函数的说明信息
三、函数的参数1:普通参数
1. 函数参数的作用
假如开发一个 func_sum
的函数,函数能够实现 两个数字的求和 功能:
# 函数定义
def func_sum():
"""两个数字的求和"""
num1 = 10
num2 = 20
result = num1 + num2
print("%d + %d = %d" % (num1, num2, result))
# 函数调用
func_sum()
- 以上函数只能处理 固定数值 的相加
- 函数参数,可以解决上面的问题,可以传递数据给函数内部,增加函数的 通用性
2. 带参数函数的使用
2.1 带参数函数的定义和调用
函数定义时的参数叫 形参,函数调用时的参数叫 实参
带参数函数的定义格式:
def 函数名字(形参1,形参2,……): 函数体代码块
带参数函数的调用格式:
函数名字(实参1,实参2,……)
示例代码:
# 带参数函数的函数定义
def func_sum(num1, num2):
"""两个数字的求和"""
result = num1 + num2
print("%d + %d = %d" % (num1, num2, result))
# 带参数函数的调用
func_sum(20, 30)
2.2 函数执行流程
- 函数调用时,按照函数定义的形参顺序,实参 一一对应 传递给形参
2.3 形参的作用域
- 作用域:变量起作用的范围
- 形参的作用域:只在定义函数的代码块 中
# 形参作用域仅在函数内部, 所以不同函数的同名参数,互不影响
def func_sum(num1, num2):
result = num1 + num2
print(result)
def func_sub(num1, num2):
result = num1 - num2
print(result)
func_sum(1, 3)
func_sub(4, 4)
四、函数的返回值
1. 函数返回值的作用
- 开发中,有时会希望 一个函数执行结束后,告诉调用者一个结果,以便调用者针对具体的结果做后续的处理
- 返回值 是 函数给调用方提供的结果
前面接触到返回值的例子:
"""
返回值变量 = input()
返回值变量 = len(容器变量)
"""
# 从键盘输入一个内容,内容返回给name赋值
name = input('请输入你的名字:')
print(name)
my_str = 'hello'
# 获取my_str内容的元素个数,返回给n赋值
n = len(my_str)
print(n)
2. return关键字的使用
2.1 通过return给函数设置返回值
return
关键字只能使用在函数中- 在函数中使用
return
关键字可以中断函数,同时也返回一个结果 - 调用函数一方,可以 使用变量 来 接收 函数的返回结果
"""
函数定义格式:
def 函数名():
return 结果
函数调用格式:
返回值变量 = 函数名()
"""
def func_sum(num1, num2):
"""两个数字的求和"""
result = num1 + num2
return result # 中断函数,同时也返回一个结果
# 函数调用:返回值变量 = 函数名()
ret = func_sum(20, 30)
print(ret)
2.2 函数默认返回值
- 函数内部没有任何return语句,默认返回None,表示没有任何数据
- return不设置返回值,默认也返回None
# 函数定义,函数内部没有任何return语句
def normal_func():
print('^_^')
# 函数定义,return不设置返回值
def return_test():
return
# 函数调用
ret1 = normal_func()
print(ret1) # None
ret2 = return_test()
print(ret2) # None
2.3 return中断函数
- 函数一旦执行return,函数内return下一句往后的代码不会执行
# 函数定义
def func():
print('不努力,你来深圳干嘛?')
return
print('我想玩游戏')
# 函数调用
func()
运行结果:
不努力,你来深圳干嘛?
五、4种函数的类型
1. 4 种函数类型的分类
函数根据有没有参数,有没有返回值,可以相互组合,一共有4种
- 无参数,无返回值
- 无参数,有返回值
- 有参数,无返回值
- 有参数,有返回值
定义函数时,是 根据实际的功能需求来设计 的,所以不同开发人员编写的函数类型各不相同
2. 无参数,无返回值的函数
"""无参数,无返回值的格式
函数定义:
def 函数名():
函数体
函数调用:
函数名()
"""
# 函数定义
def menu():
"""功能菜单"""
print('='*20)
print('= 1. 添加学生')
print('= 2. 删除学生')
print('= 3. 查询学生')
print('=' * 20)
# 函数调用
menu()
3. 无参数,有返回值的函数
"""无参数,有返回值的函数
函数定义:
def 函数名字():
return 返回结果
函数调用:
返回值变量 = 函数名字()
"""
# 函数定义
def get_pi():
"""
获取圆周率
:return: 返回圆周率
"""
return 3.14
# 函数调用
pi = get_pi()
print('圆周率为:%f' % pi)
4. 有参数,无返回值的函数
"""有参数,无返回值的函数
函数定义:
def 函数名字(形参1,形参2,……):
函数体
函数调用:
函数名(实参1,实参2,……)
"""
# 函数定义
def print_char(num, char):
"""
功能:打印指定数量的字符
:param num: 打印字符的个数,整型
:param char: 打印的字符,字符串格式
:return: None
"""
print(num * char)
# 函数调用
print_char(5, '^_^ ')
5. 有参数,有返回值的函数
"""有参数,有返回值的函数
函数定义:
def 函数名字(形参1,形参2,……):
函数体
return 返回结果
函数调用:
返回变量 = 函数名字(实参1,实参2,……)
"""
# 函数定义
def func_sum(n):
"""
功能:实现1~n累加和
:param n: n 控制累加的范围
:return: 累加后的最终结果
"""
# 1. 设置条件变量
i = 1
_sum = 0
# 2. while 条件(i <= n):
while i <= n:
# 3. 累加
_sum += i
# 4. 条件变量改变
i += 1
# 5. 循环外面,返回累加的最终结果
return _sum
# 函数调用
ret = func_sum(100)
print(ret)
六、函数的嵌套调用
1. 函数的嵌套调用
- 一个函数里面 又调用 了 另外一个函数,这就是 函数嵌套调用
# 定义fun01函数
def fun01():
print('开始调用fun01')
print('结束调用fun01')
# 定义fun02函数,在代码块中间调用fun01
def fun02():
print('开始调用fun02')
# 调用fun01
fun01()
print('结束调用fun02')
# 函数调用
fun02()
- 如果函数
func02
中,调用了另外一个函数func01
- 那么执行到调用
func01
函数时,会先把函数func01
中的任务都执行完 - 才会回到
func02
中调用函数func01
的位置,继续执行后续的代码
- 那么执行到调用
2. 函数嵌套的应用
2.1 打印多行分隔线
需求:
设计一个函数,打印一行分隔线:可指定数量,可指定分隔线字符的样式 如: 一行分隔线字符的数量为5,字符样式为
'^_^ '
^_^ ^_^ ^_^ ^_^ ^_^
设计一个函数,打印n行分隔线,可指定一行分隔线字符的数量,可指定分隔线字符的样式 如:3行分隔线,一行分隔线字符的数量为5,字符样式为
'^_^ '
^_^ ^_^ ^_^ ^_^ ^_^ ^_^ ^_^ ^_^ ^_^ ^_^ ^_^ ^_^ ^_^ ^_^ ^_^
示例代码:
def print_char(num, char):
"""
功能:打印指定数量字符的分隔线
:param num: 字符的数量
:param char: 字符样式
:return: None
"""
print(num * char)
def print_lines(n, num, char):
"""
功能:打印n行分隔线
:param n: 打印的行数
:param num: 一行分隔线字符的数量
:param char: 分隔线的字符样式
:return: None
"""
# 1. 设置条件变量 i = 0
i = 0
# 2. while 条件:
while i < n:
# 3. 打印一行的分隔线
print_char(num, char)
# 4. 条件变量的改变
i += 1
# 函数调用
print_lines(3, '^_^ ', 5)
2.2 求三个数的平均值
需求:
- 设计一个函数求三个数的和
- 设计一个函数求三个数的平均值
示例代码:
"""
1. 设计一个函数求三个数的和
2. 设计一个函数求三个数的平均值
"""
def sum_3_number(a, b, c):
"""求3个数的和"""
return a + b + c
def avg_3_number(a, b, c):
"""求3个数的平均值"""
# 先对3数求和,返回值为求和后的结果
sum_result = sum_3_number(a, b, c)
# 接着,再求平均值
avg_result = sum_result / 3
# 最终平均值结果作为函数返回值
return avg_result
# 调用函数,完成对3个数求平均值
result = avg_3_number(11, 2, 55)
print("average is %.2f" % result)
七、局部变量和全局变量
1. 局部变量
- 局部变量:函数定义的形参,函数内部定义的变量
- 不同的函数,可以定义相同的名字的局部变量,但是各用个的不会产生影响
- 局部变量的作用域只在函数内部
- 局部变量的目的是 存储需要临时保存的数据
# 函数定义
def func(temp):
a = 10
print(a)
# 函数调用
func(22)
# NameError: name 'a' is not defined
# print('函数的外部:', a) # err
# print('函数的外部: ', temp) # err
2. 全局变量
2.1 全局变量
- 在函数外部定义的变量叫做 全局变量
- 全局变量能够在所有的函数中进行访问(不修改)
# 定义全局变量
num = 10
def func():
print('func num = ', num)
func() # 函数调用
print('函数的外面 num = ', num)
运行结果:
func num = 10
函数的外面 num = 10
2.2 函数内修改全局变量
2.2.1 默认不能直接修改全局变量
# 定义全局变量
num = 10
def func():
# 函数内给一个变量赋值时,重新生成一个局部变量num
# 函数内的num和外面的num没有关系
num = 250
print('func num = ', num) # 获取是函数内的num
func() # 函数调用
# 函数外获取的是全局变量的值
print('函数的外面 num = ', num)
- 函数内赋值变量 时,默认为定义并赋值局部变量
- 函数内获取的是函数内局部变量的值,函数外获取的是全局变量的值
运行结果:
func num = 250
函数的外面 num = 10
2.2.2 通过global声明修改全局变量
- 如果在函数中修改全局变量,那么就需要先使用
global
进行声明,再进行修改
# 定义全局变量
num = 10
def func():
# global num 告诉解释器,函数内部使用的num就是外面的全局变量num
global num
num = 250 # 修改全局变量
print('func num = ', num)
func() # 函数调用
print('函数的外面 num = ', num)
运行结果:
func num = 250
函数的外面 num = 250
八、函数的参数2:参数详解
1. 位置参数
- 函数调用时,按形参的位置,从左往右,一一匹配传递参数
- 位置参数必须一一对应,缺一不可
# 函数定义
def func(num1, num2):
print('num1 = ', num1)
print('num2 = ', num2)
# 函数调用
func(1, 2)
2. 关键字参数
- 函数调用时,通过
形参=值
方式为函数形参传值,不用按照位置为函数形参传值,这种方式叫关键字参数 - 注意:
- 关键字参数必须在位置参数的右边
- 对同一个形参不能重复传值
# 函数定义
def func(num1, num2):
print('num1 = ', num1)
print('num2 = ', num2)
# 函数调用
func(num2=1, num1=2)
3. 缺省参数
- 形参设定默认值,称为缺省参数,也叫默认参数
- 注意:
- 调用函数时,如果没有传入默认参数对应的实参,则使用默认值
- 默认参数必须在普通参数的后边
# 默认参数必须在普通参数的后边
def func(a, b=20, c=10):
print(a, b, c)
# 函数调用
func(1) # a=1,b=20,c=10
func(1, 2) # a=1,b=2,c=10
func(1, 3, 2) # a=1,b=3,c=2
4. 不定长参数
4.1 元组型不定长参数
函数可以定义 不定长参数,用于接收任意数量的位置实参
形参变量名前面加上一个
*
,这个参数则为元
组型不定长参数
- 形参变量名一般叫:
args
- 形参变量名一般叫:
函数体使用不定长参数,直接使用变量名即可,无需加
\*
不定长参数的本质是 将传递的参数包装成了元组
# *args 为不定长参数,可以接收0~多个实参
# 把实参的1,2,3, 包装成元组(1, 2, 3)再传递, 等价于args = (1, 2, 3)
def func(*args):
# 函数内部使用,无需加*
print(args, type(args))
# 函数调用
func(1, 2, 3) # (1, 2, 3) <class 'tuple'>
4.2 字典型不定长参数
不定长参数还有一种形式 可以接收任意数量的关键字实参
定义参数时需要在形参名前添加
**
,则为字典型不定长参数,在函数体使用不定长参数,直接使用变量名即可,无需加
*
- 形参变量名一般叫:
kwargs
- 形参变量名一般叫:
这种不定长参数会将 关键字参数包装成字典
# 把实参包装成 {'city': 'sz', 'age': 18}给kwargs传递
# kwargs = {'city': 'sz', 'age': 18}
def func(name, **kwargs):
# 存在形参name, name不会被包装到字典中
print(name)
print(kwargs) # 函数内部使用,无需加*
# 实参的写法: 变量=数据,变量=数据
func(name='mike', city='sz', age=18)
注意:
- 已经存在的形参, 其对应的关键字实参 不会被包装到字典中
- 字典型可变形参必须在形参列表的最后边
版权声明:本博客所有文章除特殊声明外,均采用 CC BY-NC 4.0 许可协议。转载请注明出处 caijinbo的博客!