python基础4:函数
文章目录
一、函数
1. 函数的基本使用
1.1【理解】函数的作用
- 提高代码编写效率, 代码重用
 
1.2【重点】函数的定义和调用
-  
函数定义:
''' 定义函数: def 函数名(): 函数的代码块 ''' # 注意: 函数只是定义,不调用用户看不到没有效果的 def say_hello(): print("hello 1") print("hello 2") print("hello 3") -  
函数调用:
''' 函数名() ''' say_hello() 
1.3【理解】函数的执行过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l5naBQRy-1643209382484)(assets/image-20200902180709113-9041229.png)]
1.4【记忆】函数的文档注释
- 函数体内第一行多行注释即为函数的文档注释,主要写函数的描述信息
 
# 函数的文档注释: 函数体内第一行多行注释即为函数的文档注释,主要写函数的描述信息
# 函数定义
def foo():
    """
    作用: 计算1+2的结果,并打印输出
    """
    result = 1 + 2
    print(result)
# 光标移动到函数名上,使用ctrl + q 查看函数说明
foo()
 
2. 函数的参数
2.1【理解】函数参数的作用
- 函数参数,可以传递数据给函数内部,增加函数的 通用性
 
2.2【重点】函数参数的使用
-  
带参数函数的定义格式:
def 函数名(形参1, 形参2, ...): 函数体代码块 -  
带参数函数的调用格式:
函数名(实参1, 实参2, ...) 
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LWQyec4T-1643209382486)(assets/image-20200902180742488-9041262.png)]
"""
函数定义时的参数叫 形参,函数调用时的参数叫 实参
带参数函数的定义格式:
def 函数名字(形参1,形参2,……):
    函数体代码块
带参数函数的调用格式:
函数名字(实参1,实参2,……)
"""
# 带参数函数的函数定义
# def 函数名字(形参1,形参2,……):
#     函数体代码块
def foo(num1, num2):
    result = num1 + num2
    print(f"{num1} + {num2} = {result}")
# 带参数函数的调用
# 函数名字(实参1,实参2,……)
foo(10, 20)
foo(20, 30)
 
2.3【记忆】形参的作用域
- 作用域:变量起作用的范围
 - 形参的作用域:只在定义函数的代码块 中
 
# 形参:函数定义是()里面的参数
# 作用域:变量起作用的范围
# 形参的作用域只在当前函数的内部有效,和外面没有任何关系
def func_sum(num1, num2):
    result = num1 + num2
    print(f"{num1} + {num2} = {result}")
def func_sub(num1, num2):
    result = num1 - num2
    print(f"{num1} - {num2} = {result}")
# 形参作用域仅在函数内部, 所以不同函数的同名参数,互不影响
func_sum(10, 20)
# print(num1, num2)   # NameError: name 'num1' is not defined
func_sub(100, 50)
 
3. 函数的返回值
3.1【理解】函数返回值的作用
- 开发中,有时会希望 一个函数执行结束后,告诉调用者一个结果,以便调用者针对具体的结果做后续的处理
 
"""
返回值变量 = input()
返回值变量 = len(容器变量)
"""
# 从键盘输入一个内容,内容返回给name赋值
name = input("请输入用户名: ")
print(name)
# 获取my_str内容的元素个数,返回给n赋值
my_str = "hello"
n = len(my_str)
print(n)
 
3.3【重点】通过return给函数设置返回值
"""
函数返回值作用:函数处理完,返回处理结果给调用者
return关键字:中断函数,同时也返回一个结果
函数定义格式:
def 函数名():
    return 结果
函数调用格式:
返回值变量 = 函数名()
"""
# 函数定义格式:
# def 函数名():
def func_add(num1, num2):
    result = num1 + num2
    #     return 结果
    return result
# 函数调用格式:
# 返回值变量 = 函数名()
ret = func_add(10, 20)
print(ret)
 
3.4【记忆】函数默认返回值
- 函数内部没有任何return语句,默认返回None,表示没有任何数据
 - return不设置返回值,默认也返回None
 
"""
1. 函数内部没有任何return语句,默认返回None,表示没有任何数据
2. return不设置返回值,默认有返回None
"""
# 函数定义,函数内部没有任何return语句
def foo1():
    print("^_^")
# 函数定义,return不设置返回值
def foo2():
    return
# 函数调用
ret = foo1()
print(ret)
ret = foo2()
print(ret)
 
3.5【重点】return中断函数
- 函数一旦执行return,return下一句往后的代码不会执行
 
# 函数一旦执行return,函数内return下一句往后的代码不会执行
# 函数定义
def foo():
    print("不努力,你来黑马程序员干嘛?")
    return
    print("我要玩游戏")
# 函数调用
foo()
 
4. 【重点】四种函数的类型
-  
无参数,无返回值
 -  
"""无参数,无返回值的格式 函数定义: def 函数名(): 函数体 函数调用: 函数名() """ # 函数定义 def menu(): """ 函数功能:实现打印菜单 :return: 没有返回值 """ print("功能菜单") print("="*40) print("= 1. 添加学生") print("= 2. 查询学生") print("= 3. 删除学生") print("="*40) # 函数调用 menu() -  
无参数,有返回值
 -  
"""无参数,有返回值的函数 函数定义: def 函数名字(): return 返回结果 函数调用: 返回值变量 = 函数名字() """ # 函数定义 def get_pi(): """ 返回圆周率 :return: 3.14 """ return 3.14 # 函数调用 pi = get_pi() print(pi) -  
有参数,无返回值
 -  
"""有参数,无返回值的函数 函数定义: def 函数名字(形参1,形参2,……): 函数体 函数调用: 函数名(实参1,实参2,……) """ # 函数定义 def print_char(num, char): """ 输出指定数量的字符 :param num: 字符数量 :param char: 输出的字符 :return: None """ print(char * num) # 函数调用 print_char(10, '^-^') -  
有参数,有返回值
 -  
"""有参数,有返回值的函数 函数定义: def 函数名字(形参1,形参2,……): 函数体 return 返回结果 函数调用: 返回变量 = 函数名字(实参1,实参2,……) 循环累加流程: # 1. 设置条件变量 # 2. while 条件(i <= n): # 3. 累加 # 4. 条件变量改变 # 5. 循环外面,返回累加的最终结果 """ # 函数定义 def func_sum(n): """ 求1~n的累加 :param 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(f"1~100累加: {ret}") 
5. 【理解】函数的嵌套调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-szs11Zim-1643209382487)(assets/image-20200902180821994-9041302.png)]
"""
函数的嵌套调用: 函数里面调用别的函数
"""
# 定义fun01函数
def fun01():
    print("调用fun01开始")
    print("调用fun01结束")
# 定义fun02函数,在代码块中间调用fun01
def fun02():
    print("调用fun02开始")
    fun01()
    print("调用fun02结束")
# 函数调用
fun02()
 
- 案例1-打印多行分割线:
 
"""
1. 设计一个函数,打印一行分隔线:可指定数量,可指定分隔线字符的样式
    如: 一行分隔线字符的数量为5,字符样式为'^_^ '
    ^_^ ^_^ ^_^ ^_^ ^_^
2. 设计一个函数,打印n行分隔线,可指定一行分隔线字符的数量,可指定分隔线字符的样式
    如:3行分隔线,一行分隔线字符的数量为5,字符样式为'^_^ '
    ^_^ ^_^ ^_^ ^_^ ^_^
    ^_^ ^_^ ^_^ ^_^ ^_^
    ^_^ ^_^ ^_^ ^_^ ^_^
步骤流程:
# 1. 设置条件变量 i = 0
# 2. while 条件:
    # 3. 打印一行的分隔线
    # 4. 条件变量的改变
"""
"""
1. 设计一个函数,打印一行分隔线:可指定数量,可指定分隔线字符的样式
    如: 一行分隔线字符的数量为5,字符样式为'^_^ '
    ^_^ ^_^ ^_^ ^_^ ^_^
"""
def print_char(num, char):
    """
    打印一行分隔线
    :param num: 指定数量
    :param char: 指定分隔线字符的样式
    :return: 没有返回值
    """
    print(num * char)
"""
2. 设计一个函数,打印n行分隔线,可指定一行分隔线字符的数量,可指定分隔线字符的样式
    如:3行分隔线,一行分隔线字符的数量为5,字符样式为'^_^ '
    ^_^ ^_^ ^_^ ^_^ ^_^
    ^_^ ^_^ ^_^ ^_^ ^_^
    ^_^ ^_^ ^_^ ^_^ ^_^
"""
def print_lines(n, num, char):
    """
    打印n行分隔线
    :param n: n行
    :param num: 指定一行分隔线字符的数量
    :param char: 指定分隔线字符的样式
    :return: 没有返回值
    """
    # 1. 设置条件变量 i = 0
    i = 0
    # 2. while 条件:
    while i < n:
        # 3. 打印一行的分隔线
        print_char(num, char)
        # 4. 条件变量的改变
        i += 1
# print_char(5, "^_^")
print_lines(10, 10, "^_^ ")
 
- 案例2-求三个数的平均值
 
"""
1. 设计一个函数求三个数的和
2. 设计一个函数求三个数的平均值
    # 2.1 先对3数求和,返回值为求和后的结果
    # 2.2 接着,再求平均值
    # 2.3 最终平均值结果作为函数返回值
"""
# 1. 设计一个函数求三个数的和
def func_sum(n1, n2, n3):
    """
    求出三个数的和
    :param n1: 第一个数
    :param n2: 第二个数
    :param n3: 第三个数
    :return: 返回三个数之和
    """
    return n1 + n2 + n3
# 2. 设计一个函数求三个数的平均值
def func_avg(n1, n2, n3):
    """
    求出三个数的平均值
    :param n1: 第一个数
    :param n2: 第二个数
    :param n3: 第三个数
    :return: 返回三个数平均值
    """
    #     # 2.1 先对3数求和,返回值为求和后的结果
    _sum = func_sum(n1, n2, n3)
    #     # 2.2 接着,再求平均值
    _avg = _sum / 3
    #     # 2.3 最终平均值结果作为函数返回值
    return _avg
ret = func_avg(10, 20, 30)
print(ret)
 
6. 局部变量和全局变量
6.1【记忆】局部变量和全局变量的区别
- 定义方式不同 
  
- 局部变量是定义在函数内部的变量
 - 全局变量是定义在函数外部的变量
 
 - 作用域不同 
  
- 局部变量只在定义所在的函数内部有效
 - 全局变量在所有函数内都有效,函数内和函数外都可以访问
 
 
- 局部变量:
 
"""
局部变量: 函数定义的形参、函数内部定义的变量是局部变量,局部变量只能在函数内部使用
局部变量的作用域只在函数内部
"""
# 函数定义
def foo(temp):
    a = 10
    print(a, temp)
# 函数调用
foo(22)
# print(a)    # NameError: name 'a' is not defined
# print(temp) # NameError: name 'temp' is not defined
 
- 全局变量
 
"""
1. 在函数外部定义的变量叫做 全局变量
2. 全局变量能够在所有的函数中进行访问(不修改)
"""
# 定义全局变量
g_num = 10
def foo():
    print("函数中访问全局变量: ", g_num)
foo()
print("函数外访问全局变量: ", g_num)
 
6.2【重点】通过global声明修改全局变量
- 函数内修改全局变量:先global声明全局变量,再修改
 
# 函数内修改全局变量,先global声明全局变量,再修改
# 定义全局变量
g_num = 10
def foo():
    # 使用global在函数内声明 num 是全局变量
    global g_num
    g_num = 250  # g_num 是全局变量, 修改全局变量
    print("函数中访问全局变量: ", g_num)
foo()
print("函数外访问全局变量: ", g_num)
 
7. 函数参数详解
7.1【知道】位置参数和关键字参数区别
- 位置参数:按形参的位置,从左往右,一一匹配传递参数
 - 关键字参数:通过 形参=值 方式为函数形参传值,无需和形参位置一一对应
 
位置参数:
"""
1. 函数调用时,按形参的位置,从左往右,一一匹配传递参数
2. 位置参数必须一一对应,缺一不可
"""
# 函数定义
def foo(num1, num2):
    print(num1, num2)
def foo2(name, age, sex):
    print("姓名: %s 年龄: %d 性别: %s" % (name, age, sex))
# 函数调用
foo(10, 20)
foo2("小明", 20, '男')
# foo2("小芳", '女', 30) # TypeError: %d format: a number is required, not str
 
- 关键字参数:
 
# 函数调用时,通过形参=值方式为函数形参传值
# 不用按照位置为函数形参传值,这种方式叫关键字参数
# 函数定义
def foo(name, age, sex):
    print("姓名: %s 年龄: %d 性别: %s" % (name, age, sex))
# 函数调用
# 位置参数传递: 按照形参的顺序,从左到右依次传递
# foo("小明", 20, '男')
# 关键字参数传递: 通过形参=值方式为函数形参传值, 不用按照位置为函数形参传值
foo(sex='男', name='小刘', age=22)
# 第一个参数是位置参数: 按照形参的顺序传递. 第二和第三个参数是关键字参数: 按照形参=值
#   位置参数在左边, 关键字参数在右边
foo("小李", sex='男', age=20)
# 注意1: 关键字参数必须在位置参数的右边
# SyntaxError: positional argument follows keyword argument
# foo(sex='男', "小郭",  age=20)
# 注意2: 关键字参数不能重复赋值
# SyntaxError: keyword argument repeated
# foo(name="小郭", name="小李", sex='男', age=22)
 
7.2【重点】默认形参(缺省形参)
- 形参设置默认值则为缺省参数,也叫默认参数
 - 调用函数时,如果没有传入默认参数对应的实参,则使用默认值
 - 默认参数必须在普通参数的后边
 
# 形参设定默认值,称为缺省参数,也叫默认参数
# 调用函数时,如果没有传入默认参数对应的实参,则使用默认值
# 默认参数必须在普通参数的后边
def func(a, b=20, c=30):
    print(a, b, c)
# 注意:默认参数必须在普通参数的后边
# SyntaxError: non-default argument follows default argument
# def func2(a=10, b, c):
#     print(a, b, c)
# SyntaxError: non-default argument follows default argument
# def func3(a=10,b,c=30):
#     print(a, b, c)
# 函数调用
func(1)  # func(1,20,30)
func(1, 2)  # func(1, 2, 30)
func(1, 2, 3)  # func(1, 2, 3)
 
7.3【重点】元组型不定长参数
- 形参变量名前面加上一个*,这个参数则为元组型不定长参数
 
# 函数形参变量的前面加一个*, 这个参数就是不定长参数
# 把实参的1,2,3, 包装成元组(1, 2, 3)再传递, 等价于args = (1, 2, 3)
# def func(a, b, c):
#     print(a, b, c)
# *args 不定长参数,可以接收0~多个位置实参
def func(*args):
    print(args, type(args))
# 函数调用
func()
func(1)
func(1, 2)
func(1, 2, 3)   # 发现函数定义了不定长参数, 1.先把1,2,3打包成元组 (1,2,3) 2. 再传递参数给args
 
7.4【重点】字典型不定长参数
- 定义参数时需要在形参名前添加
**,则为字典型不定长参数 - 字典型可变形参必须在形参列表的最后边
 
# 函数形参变量,前面有2个*,字典型不定长参数、也叫关键字型不定长参数
# 函数内部使用,无需加*
# **kwargs, 这个参数一定是放在最右边
# 把实参包装成 {'city': 'sz', 'age': 18}给kwargs传递
# kwargs = {'city': 'sz', 'age': 18}
# def foo(name, age, sex):
#     print(name, age, sex)
def foo(name, **kwargs):
    print(name, kwargs, type(kwargs))
# 实参的写法: 变量=数据,变量=数据
foo(name="rose", age=18, sex="male")
foo(name="tom")
foo("lily")
foo("mike", age=19, sex='male', city='sz', like=['sing', 'dance'])
# 1. 关键字参数必须在位置参数右边
# 2. args: 不定长的位置参数
# 3. kwargs: 不定长的关键字参数
# 扩展: 多种参数同时出现时的函数定义的模板:
def foo(name, *args, city="sz", **kwargs):
    print(name, args, city, kwargs)
foo("rose")     # rose () sz {}
foo("tom", city='bj')   # tom () bj {}
foo("tom", 18, 'male')  # tom (18, 'male') sz {}
# tom (18, 'male') shenzhen {'cls': 'python42期', 'like': 'python'}
foo("tom", 18, 'male', city='shenzhen', cls="python42期", like='python')









