Python基础语法【第六篇】——函数介绍

Python基础语法系列导航

1.第一篇——开发环境、变量、数据类型、运算符介绍
2.第二篇——流程控制、循环、字符串介绍
3.第三篇——列表和元组介绍
4.第四篇——字典和集合介绍
5.第五篇——部分数据类型公共方法、生成式介绍
6.第六篇——函数介绍
7.第七篇——文件操作介绍



前言

Python基础语法笔记,记录一下学习过程


提示:以下是本篇文章正文内容,下面案例可供参考

12.函数

1.函数基础

1.1 函数的作用
  • 函数就是将一段具有独立功能的代码块 整合到一个整体并命名,在需要的位置调用这个名称即可完成对应的需求。

  • 函数在开发过程中,可以更高效的实现代码重用


1.2 函数的使用步骤
1.2.1 定义函数
  • 语法:

    def 函数名(参数):
        代码1
        代码2
        ......
    
1.2.2 调用函数
  • 语法:

    函数名(参数)
    

    注意:

    1. 不同的需求,参数可有可无。
    2. 在Python中,函数必须先定义后使用
1.2.3 函数案例
  • 需求:复现ATM取钱功能

    • 分析1:搭建整体框架(复现需求)

      print('密码正确登录成功')
      # 要求显示"选择功能"界面
      
      print('查询余额完毕')
      # 要求显示"选择功能"界面
      
      print('取了2000元钱')
      # 要求显示"选择功能"界面
      
    • 分析2:确定“选择功能”界面内容

      print('查询余额')
      print('存款')
      print('取款')
      
    • 分析3:封装"选择功能",构造"选择功能"函数

      # 封装ATM机功能选项 -- 定义函数
      def select_func():
          print('-----请选择功能-----')
          print('查询余额')
          print('存款')
          print('取款')
          print('-----请选择功能-----')
      

      注意:一定是先定义函数,后调用函数。

    • 分析4:调用函数,在需要显示“选择功能”函数的位置调用函数

      print('密码正确登录成功')
      # 显示"选择功能"界面 -- 调用函数
      select_func()
      
      print('查询余额完毕')
      # 显示"选择功能"界面 -- 调用函数
      select_func()
      
      print('取了2000元钱')
      # 显示"选择功能"界面 -- 调用函数
      select_func()
      


1.3 函数的参数
  • 作用:使用户能更加自由得与函数交互,输入自己想要的数据参数。

  • 函数参数分为两种类型:

    • 形参:定义函数时候要求接收的数字

    • 实参:函数调用时候指定的数字

    • 举例:

      # 定义函数时同时定义了接收用户数据的参数a和b,a和b是形参
      def add_num2(a, b):
          result = a + b
          print(result)
      
      
      # 调用函数时传入了真实的数据10 和 20,真实数据为实参
      add_num2(10, 20)
      


1.4 函数的返回值
  • 作用:函数中,如果需要返回结果给用户,那么需要使用函数返回值。这个返回结果就是返回值。

  • 举例:

    def buy():
        print("老板,买条华子")
        return '烟'
    
    # 使用变量保存函数返回值
    goods = buy()
    print(goods)	# 烟
    


1.5 函数的说明文档

思考:定义一个函数后,如何书写程序能够快速提示这个函数的作用?

答:注释

思考:如果代码多,我们是不是需要在很多代码中找到这个函数定义的位置才能看到注释?如果想更方便的查看函数的作用怎么办?

答:函数的说明文档,help()函数调用

  • 语法:

    # 定义函数的说明文档
    def 函数名(参数):
        """ 说明文档的位置 """
        代码
        ......
        
    # 查看函数的说明文档
    help(函数名)
    
  • 举例:

    def sum_num(a, b):
        """ 求和函数 """
        return a + b
    
    
    # sum_num(a, b)
    #	求和函数
    help(sum_num)
    


1.6 函数嵌套调用

函数嵌套调用指的是一个函数里面又调用了另外一个函数

  • 举例:

    def testB():
        print('---- testB start----')
        print('这里是testB函数执行的代码...(省略)...')
        print('---- testB end----')
    
    def testA():
        print('---- testA start----')
        testB()
        print('---- testA end----')
    
    testA()
    
  • 输出效果:

    ---- testA start----
    ---- testB start----
    这里是testB函数执行的代码...(省略)...
    ---- testB start----
    ---- testA start----
    
  • 执行流程:
    在这里插入图片描述

    注意:如果函数A中,调用了另外一个函数B,那么先把函数B中的任务都执行完毕之后才会回到上次 函数A执行的位置。


1.7 总结
  • 函数的作用:封装代码,高效的代码重用

  • 函数使用步骤

    • 定义函数
    def 函数名():
        代码1
        代码2
        ...
    
    • 调用函数
    函数名()
    
  • 函数的参数:函数调用的时候可以传入真实数据,增大函数的使用的灵活性

    • 形参:函数定义时书写的参数(非真实数据)
    • 实参:函数调用时书写的参数(真实数据)
  • 函数的返回值

    • 作用:函数调用后,返回需要的计算结果
    • 写法
    return 表达式
    
  • 函数的说明文档

    • 作用:保存函数解释说明的信息
    • 写法
    def 函数名():
        """ 函数说明文档 """
    
  • 函数嵌套调用:一个函数内部嵌套调用另外一个函数



2.函数提高

2.1 变量作用域
  • 变量作用域指的是变量生效的范围,主要分为两类:局部变量全局变量

    • 局部变量:所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效。

      def testA():
          a = 100
      
          print(a)
      
      
      testA()  # 100
      print(a)  # 报错:name 'a' is not defined
      

      注意:变量a是定义在testA函数内部的变量,在函数外部访问则立即报错。

      局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量。

    • 全局变量:所谓全局变量,指的是在函数体内、外都能生效的变量。

      # 定义全局变量a
      a = 100
      
      
      def testA():
          print(a)  # 访问全局变量a,并打印变量a存储的数据
      
      
      def testB():
          print(a)  # 访问全局变量a,并打印变量a存储的数据
      
      
      testA()  # 100
      testB()  # 100
      
      • 思考1:testB函数需求修改变量a的值为200,如何修改程序?

        a = 100
        
        
        def testA():
            print(a)
        
        
        def testB():
            a = 200
            print(a)
        
        
        testA()  # 100
        testB()  # 200
        print(f'全局变量a = {a}')  # 全局变量a = 100
        
      • 思考2:在testB函数内部的a = 200中的变量a是在修改全局变量a吗?

      答:不是。观察上述代码发现,testA()得到a的数据是100,仍然是定义全局变量a时候的值。

      testB函数内部的200。综上:testB函数内部的a = 200是定义了一个局部变量。

      • 思考3:如何在函数体内部修改全局变量?

        a = 100
        
        
        def testA():
            print(a)
        
        
        def testB():
            # global 关键字声明a是全局变量
            global a
            a = 200
            print(a)
        
        
        testA()  # 100
        testB()  # 200
        print(f'全局变量a = {a}')  # 全局变量a = 200
        

        注意: global 关键字声明a是全局变量


2.2 多函数程序执行流程

一般在实际开发过程中,一个程序往往由多个函数组成,并且多个函数共享某些数据,如下案例所示:

  • 举例1:共用全局变量

    # 1. 定义全局变量
    glo_num = 0
    
    
    def test1():
        global glo_num
        # 修改全局变量
        glo_num = 100
    
    
    def test2():
        # 调用test1函数中修改后的全局变量
        print(glo_num)
        
    
    # 2. 调用test1函数,执行函数内部代码:声明和修改全局变量
    test1()
    # 3. 调用test2函数,执行函数内部代码:打印
    test2()  # 100
    
  • 举例2:返回值作为参数传递

    def test1():
        return 50
    
    
    def test2(num):
        print(num)
    
    
    # 1. 保存函数test1的返回值
    result = test1()
    
    
    # 2.将函数返回值所在变量作为参数传递到test2函数
    test2(result)  # 50
    


2.3 函数的参数
2.3.1 位置参数
  • 位置参数:调用函数时根据函数定义的参数位置来传递参数

  • 语法:

    def user_info(name, age, gender):
        print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
    
    
    user_info('TOM', 20, '男')
    

    注意:传递和定义参数的顺序及个数必须一致。

2.3.2 关键字参数
  • 关键字参数:函数调用,通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求

  • 语法:

    def user_info(name, age, gender):
        print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
    
    
    user_info('Rose', age=20, gender='女')
    user_info('小明', gender='男', age=16)
    

    注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。

2.3.3 默认参数
  • 默认参数:也叫缺省参数。用于定义函数,为参数提供默认值。函数调用时,如果为默认参数传值,则修改默认参数值;否则将使用这个默认值。

  • 语法:

    def user_info(name, age, gender='男'):
        print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
    
    
    user_info('TOM', 20)	# 您的名字是TOM, 年龄是20, 性别是男
    user_info('Rose', 18, '女')	# 您的名字是ROSE, 年龄是18, 性别是女
    

    注意:

    1. 所有位置参数必须出现在默认参数前,包括函数定义和调用
2.3.4 可变参数
  • 可变参数:也叫不定长参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。

    • 包裹位置传递语法:
    def user_info(*args):	# *参数名
        print(args)
    
    
    # ('TOM',)
    user_info('TOM')
    # ('TOM', 18)
    user_info('TOM', 18)
    

    注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。

    • 包裹关键字传递语法:
    def user_info(**kwargs):	# **参数名
        print(kwargs)
    
    
    # {'name': 'TOM', 'age': 18, 'id': 110}
    user_info(name='TOM', age=18, id=110)
    

    注意:传进的所有参数都会被kwargs变量收集,它会根据传进参数的位置合并为一个字典(dict),kwargs是字典类型,这就是包裹关键字传递。

  • 综上:无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程。


2.4 函数的返回值
  • 思考1:如果一个函数如些两个return (如下所示),程序如何执行?
def return_num():
    return 1
    return 2


result = return_num()
print(result)  # 1

答:只执行了第一个return,原因是因为return可以退出当前函数,导致return下方的代码不执行。

  • 思考2:如果一个函数要有多个返回值,该如何书写代码?
def return_num():
    return 1, 2


result = return_num()
print(result)  # (1, 2)

注意:

  1. return a, b写法,返回多个数据的时候,默认是元组类型
  2. return后面可以连接列表、元组或字典,以返回多个值。


2.5 拆包和交换变量值
2.5.1 拆包
  • 拆包:元组

    def return_num():
        return 100, 200
    
    
    num1, num2 = return_num()
    print(num1)  # 100
    print(num2)  # 200
    
  • 拆包:字典

    dict1 = {'name': 'TOM', 'age': 18}
    a, b = dict1
    
    # 对字典进行拆包,取出来的是字典的key
    print(a)  # name
    print(b)  # age
    
    print(dict1[a])  # TOM
    print(dict1[b])  # 18
    
2.5.2 交换变量值
  • 需求:有变量a = 10b = 20,交换两个变量的值

    • 方法1:借助第三变量存储数据

      # 1. 定义中间变量
      c = 0
      
      # 2. 将a的数据存储到c
      c = a
      
      # 3. 将b的数据20赋值到a,此时a = 20
      a = b
      
      # 4. 将之前c的数据10赋值到b,此时b = 10
      b = c
      
      print(a)  # 20
      print(b)  # 10
      
    • 方法2:

      a, b = 1, 2		
      a, b = b, a		
      
      print(a)  # 2
      print(b)  # 1
      


2.6 引用
2.6.1 了解引用
  • 在python中,值是靠引用来传递来的。

  • 我们可以用id()来判断两个变量是否为同一个值的引用。 我们可以将id值理解为那块内存的地址标识

    # 1. int类型
    a = 1
    b = a
    
    print(b)  # 1
    
    print(id(a))  # 140708464157520
    print(id(b))  # 140708464157520, 两个变量为同一个值的引用,内存地址相同
    
    a = 2
    print(b)  # 1 ,说明int类型为不可变类型 
    
    print(id(a))  # 140708464157552,此时得到是的数据2的内存地址
    print(id(b))  # 140708464157520
    
    
    # 2. 列表
    aa = [10, 20]
    bb = aa
    
    print(id(aa))  # 2325297783432
    print(id(bb))  # 2325297783432, 两个列表为同一个值的引用,内存地址相同
    
    
    aa.append(30)
    print(bb)  # [10, 20, 30], 列表为可变类型
    
    print(id(aa))  # 2325297783432
    print(id(bb))  # 2325297783432, 由此说明可变数据类型在增删修时无需新建一个对象, 而不可变需要。
    
2.6.2 引用当实参
  • 举例:可以看作是2.6.1的一个扩展

    # 将这段代码运行,观察它们的id,再联系2.6.1了解引用的内容进行巩固理解
    def test1(a):
        print(a)
        print(id(a))
    
        a += a
    
        print(a)
        print(id(a))
    
    
    # int:计算前后id值不同
    b = 100
    test1(b)
    
    # 列表:计算前后id值相同
    c = [11, 22]
    test1(c)
    


2.7 总结
  • 变量作用域
    • 全局变量:函数体内外都能生效
    • 局部变量:当前函数体内部生效
  • 函数多返回值写法
return 表达式1, 表达式2...
  • 函数的参数

    • 位置参数
      • 形参和实参的个数和书写顺序必须一致
    • 关键字参数
      • 写法: key=value
      • 特点:形参和实参的书写顺序可以不一致;关键字参数必须书写在位置参数的后面
    • 默认参数
      • 写法:key=vlaue
    • 可变参数
      • 收集所有位置参数,返回一个元组
    • 可变关键字参数
      • 收集所有关键字参数,返回一个字典
  • 引用:Python中,数据的传递都是通过引用



3.函数进阶

3.1 递归函数
  • 递归定义:递归是一种编程思想,调用函数自身的方式

  • 递归应用场景:

    1. 在我们日常开发中,如果要遍历一个文件夹下面所有的文件,通常会使用递归来实现;
    2. 很多算法都离不开递归,例如:快速排序。
  • 递归的2大特点:

    • 递归链条:计算过程存在递归链条,如n(n-1)! 构成一条递归链条
    • 递归基例:存在一个或多个不需要再次递归的基例,如n=0时候,不再递归
  • 递归的实现:函数+分支语句

    1. 递归本身是一个函数,需要函数定义方式描述
    2. 函数内部,采用分支语句对输入参数进行判断基例或链条
  • 递归代码举例:3以内数字累加和

    # 3 + 2 + 1
    def sum_numbers(num):
        # 1.如果是1,直接返回1 -- 出口
        if num == 1:
            return 1
        # 2.如果不是1,重复执行累加并返回结果
        return num + sum_numbers(num-1)
    
    
    sum_result = sum_numbers(3)
    # 输出结果为6
    print(sum_result)
    

    执行结果:

    在这里插入图片描述


3.2 lambda表达式(匿名函数)
3.2.1 lambda的应用场景
  • 如果一个函数有一个返回值,并且只有一句代码,可以使用lambda表达式简化
3.2.2 lambda语法
lambda 参数列表 : 表达式

注意:

  1. lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用。
  2. lambda表达式能接收任何数量的参数但只能返回一个表达式的值。
3.2.3 lambda示例
# 函数
def fn1():
    return 200


print(fn1)		# 打印函数fn1的内存地址
print(fn1())


# lambda表达式
fn2 = lambda: 100
print(fn2)		# 打印函数fn2的内存地址
print(fn2())

# lambda表达式实现计算a + b
fn3 = lambda a, b : a + b
print(fn3(1, 2))

注意:直接打印lambda表达式,输出的是此lambda的内存地址

3.2.4 lambda的参数形式
  • 无参数

    fn1 = lambda: 100
    print(fn1())
    
  • 一个参数

    fn1 = lambda a: a
    print(fn1('hello world'))
    
  • 默认参数

    fn1 = lambda a, b, c=100: a + b + c
    print(fn1(10, 20))
    
  • 可变参数 *args

    fn1 = lambda *args: args
    print(fn1(10, 20, 30))
    

    注意:这里的可变参数传入到lambda之后,返回值为元组

  • 可变参数 **kwargs

    fn1 = lambda **kwargs: kwargs
    print(fn1(name='python', age=20))
    

    注意:这里的可变参数传入到lambda之后,返回值为字典

3.2.5 lambda的应用
  • 带判断的lambda

    fn1 = lambda a, b: a if a > b else b
    print(fn1(1000, 500))	# 1000
    
  • 列表数据按字典key的值排序

    students = [
        {'name': 'TOM', 'age': 20},
        {'name': 'ROSE', 'age': 19},
        {'name': 'Jack', 'age': 22}
    ]
    
    # 按name值升序排列
    # reverse默认按升序排序
    students.sort(key=lambda x: x['name'])
    print(students)
    
    # 按name值降序排列
    students.sort(key=lambda x: x['name'], reverse=True)
    print(students)
    
    # 按age值升序排列
    students.sort(key=lambda x: x['age'])
    print(students)
    


3.3 总结
  • 递归

    • 函数内部自己调用自己
    • 必须有出口
  • lambda表达式

    • 语法
    lambda 参数列表: 表达式
    
    • lambda的参数形式

      • 无参数
      lambda: 表达式
      
      • 一个参数
      lambda 参数: 表达式
      
      • 默认参数
      lambda key=value: 表达式
      
      • 不定长位置参数
      lambda *args: 表达式
      
      • 不定长关键字参数
      lambda **kwargs: 表达式
      



4.高阶函数

把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。

4.1 高阶函数举例
  • 在Python中,abs()函数可以完成对数字求绝对值计算

    abs(-10)  # 10
    
  • round()函数可以完成对数字的四舍五入计算

    round(1.2)  # 1
    round(1.9)  # 2
    
  • 需求:任意两个数字,按照绝对值整理数字后再进行求和计算

    • 方法1:

      def add_num(a, b):
          return abs(a) + abs(b)
      
      
      result = add_num(-1, 2)
      print(result)  # 3
      
    • 方法2:

      def sum_num(a, b, f):
          return f(a) + f(b)
      
      
      result = sum_num(-1, 2, abs)
      print(result)  # 3
      

      注意:两种方法对比之后,发现,方法2的代码会更加简洁,函数灵活性更高。当我们需求改变不再是求绝对值时,只需更改一处即实参的修改。而不用像方法1一样修改多处。


4.2 内置高阶函数
4.2.1 map()
  • 作用:map(func, lst),将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表Python2 / 迭代器Python3 返回。

  • 举例:

    # 需求:计算list1序列中各个数字的2次方
    
    list1 = [1, 2, 3, 4, 5]
    
    def func(x):
        return x ** 2
    
    result = map(func, list1)
    
    print(result)	# <map object at 0x0000013769653198>, 迭代器对象内存地址
    print(list(result))		# [1, 4, 9, 16, 25]
    
4.2.2 reduce()
  • 作用:reduce(func,lst),其中func必须有两个参数。每次func计算的结果继续和lst序列的下一个元素做累积计算。

    注意:reduce()传入的参数func必须接收2个参数。

  • 举例:

    # 需求:计算list1序列中各个数字的累加和
    
    import functools
    
    list1 = [1, 2, 3, 4, 5]
    
    
    def func(a, b):
        return a + b
    
    
    result = functools.reduce(func, list1)
    
    print(result)  # 15
    

    注意:reduce()使用时先导入functools模块

4.2.3 filter()
  • 作用:filter(func, lst)函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象。如果要转换为列表, 可以使用 list() 来转换。

  • 举例:

    list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    
    def func(x):
        return x % 2 == 0
    
    
    result = filter(func, list1)
    
    print(result)  # <filter object at 0x0000017AF9DC3198>, 过滤器对象内存地址
    print(list(result))  # [2, 4, 6, 8, 10]
    


4.3 总结
  • 高阶函数

    • 作用:把函数作为参数传入,化简代码
    • 内置高阶函数
      • map()
      • reduce()
      • filter()



总结

有误之处,欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值