018.Python基础进阶_初识函数

无奋斗不青春

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈
入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈
虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈
PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈
Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈
优 质 资 源 下 载 :👉👉 资源下载合集 👈👈

分隔线

函数

基本概念

  • 概念
    • 函数是一种可重复使用的代码块,它接受输入参数、执行操作,并返回一个输出结果
    • 函数可以接受任意数量的输入参数,并且可以不返回任何输出结果。
    • 函数可以在程序中的任何地方定义,包括在其他函数内部。
    • 当函数被调用时,程序的控制流会转移到函数内部,执行函数中的代码,然后返回到调用函数的代码位置

作用

  • 1、 方便代码的重用
  • 2、 分解任务,简化程序逻辑
  • 3、 使代码更加模块化

分类

  • 内建函数(内置函数)
  • 三方函数
  • 自定义函数

定义

  • 语法
    def function_name(arg1: str, arg2: int):
        """
        document
        """
        statement(arg)
        return num
        
    # 注意:在创建自定义类方法的时候必须加self参数,否则会报错
    
  • 说明
    def                     # 函数定义关键字
    function_name           # 函数名
    arg1                    # 参数1
    str                     # 参数1类型(仅仅是用户调用参数时,告诉用户写入什么类型的值)
    arg2                    # 参数2
    int                     # 参数2类型(仅仅是用户调用参数时,告诉用户写入什么类型的值)
    document                # 函数描述文档(用户可以通过help(函数名)查看描述文档)
    statement(arg)          # 代码语句或其他函数,带()为调用
    return                  # 函数返回值关键字
    num                     # 函数返回值
    

参数

定义

  • 参数的定义
    • 函数在定义的时候,函数名后面的括号中定义的参数
  • 参数传递的形式
    • 位置参数:按位置传递的参数
    • 关键字参数:通过关键字指定传给某个参数,且关键字参数必须写在位置参数之后

场景

  • 需要动态的调整函数体中某一个(或多个)处理信息,则可以以参数的形式收到相关数据
  • 示例
    def mySum():
        print(1 + 2)
        
    mySum()         # --> 3
    
    • 这一段代码,我们写了一个计算1+2的函数,但是也仅仅是能计算1+2,如果我要计算 2+,、3+2等等,那这个函数就不能实现了,难道要重新定义多个函数?
    def mySum():
        print(1 + 2)
    
    def mySum2():
        print(2 + 2)
    
    def mySum3():
        print(3 + 2)
    
    mySum()         # --> 3
    mySum2()        # --> 4
    mySum3()        # --> 5
    
    • 但是,这个明显不符合函数的方便代码的重用的特性!那么,这个时候我们就需要用到参数了
    def mySum(a):
        print(a + 2)
    
    
    mySum(1)         # --> 3
    mySum(2)         # --> 4
    mySum(3)         # --> 5
    
    • 加入了参数之后,使用起来就方便多了,直接在调用函数的时候把要加的数值穿进去就可以了。但是,这里我们只能是加2,那我想加其他数值呢?同样的,再用一个参数代替就可以了。多个参数中间用“,”分隔
    def mySum(a, b):
        print(a + b)
    
    
    mySum(1, 2)         # --> 3
    mySum(2, 3)         # --> 5
    mySum(3, 5)         # --> 8
    

参数分类

  • 形参: 形式参数,在函数定义时用来接收传入参数的变量
    形参是函数定义时的概念,可以理解为函数内部使用的一种占位符(变量),用于接收传入的实参
  • 实参: 实际参数,在函数调用的时候括号内传入的数据
  • 在这里插入图片描述

参数形式

  • 位置参数
  • 默认参数
  • 关键字参数
  • 不定长参数
位置参数
  • 位置参数: 又叫必备参数&必需参数,表示的是形参和实参之间的关系

  • 调用的时候形参和实参要按照顺序一一对应,不能多传,也不能少传,位置也需要一一对应

  • 图解

    • 在这里插入图片描述
  • 示例代码

    def person_info(name: str, age: int):
        print(f'我的姓名是:{name}')
        print(f'我的年龄是:{age}')
    
    
    person_info('失心疯', 36)
    
    # -----输出结果-----
    # 我的姓名是:失心疯
    # 我的年龄是:36
    
    
    person_info(36, '失心疯')
    
    # -----输出结果-----
    # 我的姓名是:36
    # 我的年龄是:失心疯
    
默认参数
  • 默认参数: 又叫缺省参数。在函数定义的时候,给形式参数一个默认值(缺省值)

    • 在函数调用的时候没有传入该参数的实际参数时,则直接使用这个缺省值;
    • 在函数调用的时候,若传入了该参数的实际参数,则使用传入的实参值,默认值不会生效;
  • 注意事项

    默认参数的作用:默认参数可以简化函数调用的过程,只需要传入少量参数就可以实现调用的过程;
    默认参数必须放到位置参数的后面,否则会报语法错误:SyntaxError: non-default argument follows default argument(SyntaxError:非默认参数跟随默认参数)

  • 图解1
    在这里插入图片描述

  • 示例1代码

    def person_info(age: int, name: str = '失心疯'):
        print(f'我的姓名是:{name}')
        print(f'我的年龄是:{age}')
    
    
    person_info(36)
    
    # -----输出结果-----
    # 我的姓名是:失心疯
    # 我的年龄是:36
    
    
    person_info(36, '疯子')
    
    # -----输出结果-----
    # 我的姓名是:疯子
    # 我的年龄是:36
    
  • 图解2在这里插入图片描述

  • 示例2代码

    def person_info(name: str = '失心疯', age: int ):
        print(f'我的姓名是:{name}')
        print(f'我的年龄是:{age}')
    
    
    person_info(36)
    
    # -----输出结果-----
    File "E:\Projecs\Python\11-函数\01-函数定义.py", line 52
        def person_info(name: str = '失心疯', age: int ):
                                                          ^
    SyntaxError: non-default argument follows default argument
    
关键字参数
  • 关键字参数: 也是相对于位置参数来讲的,在函数调用的时候使用关键字进行传值,可以做到不需要与位置参数的位置一一对应;

    • 关键字的名字需要从形式参数中去选择,也就是在函数调用传值的时候需要带上形式参数的名称
    • 关键字参数与位置参数在函数定义的时候并没有区别,区别的是在函数调用的时候
  • 注意事项

    关键字参数的作用:可以提高函数的调用时候的可读性,更容易理解实际参数的意义
    关键字参数和位置参数的区别:关键字参数在调用时可以不按照顺序进行传参,可以交换顺序

  • 应用场景

    def person_info(name: str, sex: str = '男', age: int = 36):
        print(f'我的姓名是:{name},年龄是:{age},性别是:{sex}')
    
    
    person_info('张三', '男', 18)           # --> 我的姓名是:张三,年龄是:18,性别是:男
    person_info('李四', '男', 20)           # --> 我的姓名是:李四,年龄是:20,性别是:男
    person_info('王五', '男', 19)           # --> 我的姓名是:王五,年龄是:19,性别是:男
    person_info('赵六', '男', 17)           # --> 我的姓名是:赵六,年龄是:17,性别是:男
    person_info('洪七', '男', 23)           # --> 我的姓名是:洪七,年龄是:23,性别是:男
    
  • 从上面代码可以看出

    • 函数调用中,这些人员的性别全部都是男,而且我也写了性别默认参数是男
    • 每次调用函数的时候我们都要写上这个性别,就显得非常累赘,那我们是不是可以直接省略呢?
  • 试一下…

    def person_info(name: str, sex: str = '男', age: int = 36):
        print(f'我的姓名是:{name},年龄是:{age},性别是:{sex}')
    
    
    person_info('张三', 18)           # --> 我的姓名是:张三,年龄是:36,性别是:18
    person_info('李四', 20)           # --> 我的姓名是:李四,年龄是:36,性别是:20
    person_info('王五', 19)           # --> 我的姓名是:王五,年龄是:36,性别是:19
    person_info('赵六', 17)           # --> 我的姓名是:赵六,年龄是:36,性别是:17
    person_info('洪七', 23)           # --> 我的姓名是:洪七,年龄是:36,性别是:23
    
  • 哦豁…

    • 从运行结果来看,这明显是出了大问题了,所有人的年龄都变成了默认的36岁了,性别都变成了我们想要传入的年龄值了,而默认的性别没有了…
  • 尴了个尬…

    • 原因是,我们在sex参数的位置,传入了一个值,那么sex参数就会接收到这个实参值,导致形参设置的默认值失效,而age参数位置没有传值,所有age参数就用了默认值
    • 为了解决这个问题,关键字参数就该出场了…
  • 图解

    • 在这里插入图片描述
  • 示例代码

    def person_info(name: str, sex: str = '男', age: int = 36):
        print(f'我的姓名是:{name},年龄是:{age},性别是:{sex}')
    
    
    person_info('张三', age=18)           # --> 我的姓名是:张三,年龄是:18,性别是:男
    person_info('李四', age=20)           # --> 我的姓名是:李四,年龄是:20,性别是:男
    person_info('王五', age=19)           # --> 我的姓名是:王五,年龄是:19,性别是:男
    person_info('赵六', age=17)           # --> 我的姓名是:赵六,年龄是:17,性别是:男
    person_info('洪七', age=23)           # --> 我的姓名是:洪七,年龄是:23,性别是:男
    
    # 调用函数时,传入了两个实参
    # 一个是通过位置传入的值,name参数接收
    # 另一个是通过关键字参数传入的值,默认参数age接收
    # 函数中还有一个默认参数sex没有传值,直接用默认值
    
  • 从代码运行结果可以看到,通过关键字参数传值,完美的解决我们需求

不定长参数
  • 不定长参数: 能够接收传入不限定个数实参的参数。实参可以传0个,也可以传任意个
  • 不定长参数有两种表现形式:*args**kwargs
    1. *args不定长 位置传参,接收函数调用时多余的位置参数,并打包成元组
    2. **kwargs不定长 关键字传参,接收函数调用时多余的关键字参数,并打包成字典
    3. *args在函数内部的表现形式是元组,**kwargs在函数内部的表现形式是字典
    4. *args加在其他位置参数的后面,**kwargs加在*args的后面,否则会报错
    5. 在函数中可以只有一个*args或者是**kwargs,不能有多个,会报错也没意义
    6. 函数定义时参数使用argskwargs是为了提高代码可读性,实际上可以替换成其他任何字符
  • *args应用场景
    • 我们现在需要定义一个函数,来批量发送右键,函数需要接收右键标题和邮箱
      def out_mail(title:str, mailid1:str, mailid2:str):
          print(f'【{title}】邮件发送给了:{mailid1}')
          print(f'【{title}】邮件发送给了:{mailid2}')
          
      
      # 函数调用
      out_mail('晚餐邀请函', '12356@qq.com', '223344@163.com')
      
      # -----输出结果-----
      【晚餐邀请函】邮件发送给了:12356@qq.com
      【晚餐邀请函】邮件发送给了:223344@163.com
      
    • 我们通过位置参数定义了这个函数,但是有一个问题,如果我们需要发送的人员很多的时候,那岂不是需要在定义的时候写N个位置参数?这显然…
    • 这个时候,我们的不定长参数就该出场了…
      # 首先我们在定义函数的时候加一个不定长参数 *mailid,然后在函数体内打印看一下
      def out_mail(title: str, *mailid: str):
          print('title:', title, type(title))
          print('mailid:', mailid, type(mailid))
          
      
      # 函数调用
      out_mail('晚餐邀请函', '12356@qq.com', '223344@163.com')
      
      # -----输出结果-----
      title: 晚餐邀请函 <class 'str'>
      mailid: ('12356@qq.com', '223344@163.com') <class 'tuple'>
      
    • 从上面代码中可以看到,函数调用时候,我们传入了多个邮箱地址,但是输出结果的时候可以看到多个邮箱地址被打包成了一个元组
    • 那么,我们在函数体里面就可以循环这个元组来进行操作元组里面的每个元素了…
      def out_mail(title: str, *mailid: str):
          for id in mailid:
              print(f'【{title}】邮件发送给了:{id}')
      
      
      # 函数调用1
      out_mail('晚餐邀请函', '12356@qq.com', '223344@163.com')
      
      # -----输出结果1-----
      【晚餐邀请函】邮件发送给了:12356@qq.com
      【晚餐邀请函】邮件发送给了:223344@163.com
       
      
      # 函数调用2
      out_mail('晚餐邀请函', '12356@qq.com', '223344@163.com', 'shixinfeng@163.com', '1235524@qq.com')
      
      # -----输出结果2-----
      【晚餐邀请函】邮件发送给了:12356@qq.com
      【晚餐邀请函】邮件发送给了:223344@163.com
      【晚餐邀请函】邮件发送给了:shixinfeng@163.com
      【晚餐邀请函】邮件发送给了:1235524@qq.com
      
    • 在定义函数的时候,不定长位置参数是用 * + 任意字符 都可以,但是我们一般都是默认用*args
      def out_mail(title: str, *args: str):
          for id in args:
              print(f'【{title}】邮件发送给了:{id}')
      
      
      # 函数调用
      out_mail('晚餐邀请函', '12356@qq.com', '223344@163.com', 'shixinfeng@163.com', '1235524@qq.com')
      
      # -----输出结果2-----
      【晚餐邀请函】邮件发送给了:12356@qq.com
      【晚餐邀请函】邮件发送给了:223344@163.com
      【晚餐邀请函】邮件发送给了:shixinfeng@163.com
      【晚餐邀请函】邮件发送给了:1235524@qq.com
      
  • **kwargs应用场景
    • 上面的函数我们可以批量的发送给多个邮箱地址了,但是我们需要在每个邀请函的开头标注收件人的问候(xxx先生,您好!)
    • 此时,上面的不定长位置参数*args就做不到了,就需要用到**kwargs不定长关键字参数了…
      def out_mail(title: str, **mailid: str):
          print('title:', title, type(title))
          print('mailid:', mailid, type(mailid))
      
      
      # 函数调用
      out_mail('晚宴邀请函', 李先生='12332@qq.com', 王女士='2323231@163.com')
      
      # -----输出结果-----
      title: 晚宴邀请函 <class 'str'>
      mailid: {'李先生': '12332@qq.com', '王女士': '2323231@163.com'} <class 'dict'>
      
      
    • 从上面代码的输出结果可以看出来,`mailid参数接收了函数调用时传过来的多个关键字参数传值,并且将其打包成了一个字典
    • 那么,在函数体内部,我们就可以对这个字典进行循环取值操作了…
      def out_mail(title: str, **mailid: str):
          for k, v in mailid.items():
              print(f'【{title}】')
              print(f'{k},您好!\n    我们盛情邀请您今晚参加我们的晚宴!')
              print(f'邮件发送给{v}'.rjust(27,' '))
              print()
      
      
      # 函数调用
      out_mail('晚宴邀请函', 李先生='12332@qq.com', 王女士='2323231@163.com')
      
      # -----输出结果-----
      【晚宴邀请函】
      李先生,您好!
          我们盛情邀请您今晚参加我们的晚宴!
                邮件发送给12332@qq.com
      
      【晚宴邀请函】
      王女士,您好!
          我们盛情邀请您今晚参加我们的晚宴!
             邮件发送给2323231@163.com
      
    • 从上面代码输出结果可以看出来,已经满足我们的需求了
    • 在定义函数的时候,不定长关键字参数是用 ** + 任意字符 都可以,但是我们一般都是默认用**kwargs
      def out_mail(title: str, **kwargs: str):
          for k, v in kwargs.items():
              print(f'【{title}】')
              print(f'{k},您好!\n    我们盛情邀请您今晚参加我们的晚宴!')
              print(f'邮件发送给{v}'.rjust(27,' '))
              print()
      
      
      # 函数调用
      out_mail('晚宴邀请函', 李先生='12332@qq.com', 王女士='2323231@163.com')
      
      # -----输出结果-----
      【晚宴邀请函】
      李先生,您好!
          我们盛情邀请您今晚参加我们的晚宴!
                邮件发送给12332@qq.com
      
      【晚宴邀请函】
      王女士,您好!
          我们盛情邀请您今晚参加我们的晚宴!
             邮件发送给2323231@163.com
      
  • 特别注意:
    • 不定长参数,我们在函数调用时,实参并不是传入元组和字典,而是传入位置参数和关键字参数

函数的装包和拆包

装包

  • 装包:把传递的参数,包装成一个集合(元组/字典),称之为装包
  • 示例
    def out_mail1(title: str, *args: str):
        print(type(args), args)
    
    
    def out_mail2(title: str, **kwargs: str):
        print(type(kwargs), kwargs)
    
    
    out_mail1('装包过程', '12231@qq.com', '33371712@163.com', '938722@qq.com')
    
    # -----输出结果-----
    # <class 'tuple'> ('12231@qq.com', '33371712@163.com', '938722@qq.com')
    
    
    out_mail2('装包过程', 李先生='12231@qq.com', 王女士='33371712@163.com', 赵老爷='938722@qq.com')
    
    # -----输出结果-----
    # <class 'dict'> {'李先生': '12231@qq.com', '王女士': '33371712@163.com', '赵老爷': '938722@qq.com'}
    
    • 在这里插入图片描述

拆包

  • 拆包:把集合参数分解成单独的个体,称之为拆包

    列表、元组、集合通过一个星号*拆包,字典通过两个星号**拆包

  • 示例1
    def out_mail(*args):
        print('拆包前:', args)
        # 拆包操作,元组拆包,通过一个星号 *
        print('拆包后:', *args)
    
    
    out_mail('12231@qq.com', '33371712@163.com', '938722@qq.com')
    
    # -----输出结果-----
    拆包前: ('12231@qq.com', '33371712@163.com', '938722@qq.com')
    拆包后: 12231@qq.com 33371712@163.com 938722@qq.com
    
    • 代码运行结果可以看到,拆包前是一个元组,拆包后变成了单独的元素
  • 示例2
    def out_mail(**kwargs):
        print('拆包前:', kwargs)
        # 拆包操作,元组拆包,通过一个星号 *
        print('拆包后:', **kwargs)
    
    
    out_mail(MrLi='12231@qq.com', MsZhao='33371712@163.com', MasterHe='938722@qq.com')
    
    # -----输出结果-----
    拆包前: {'MrLi': '12231@qq.com', 'MsZhao': '33371712@163.com', 'MasterHe': '938722@qq.com'}
    
    Traceback (most recent call last):
      File "E:\Projecs\Python\11-函数\01-函数定义.py", line 229, in <module>
        out_mail(MrLi='12231@qq.com', MsZhao='33371712@163.com', MasterHe='938722@qq.com')
      File "E:\Projecs\Python\11-函数\01-函数定义.py", line 226, in out_mail
        print('拆包后:', **kwargs)
    TypeError: 'MrLi' is an invalid keyword argument for print()
    
    • 输出结果可以看到,程序报错了,原因是字典拆包后,不能直接打印到控制台,但是可以直接使用
    def person(MrLi, MsZhao, MasterHe):
        print(MrLi)
        print(MsZhao)
        print(MasterHe)
    
    
    def out_mail(**kwargs):
        print('拆包前:', kwargs)
        # 拆包操作,元组拆包,通过一个星号 *
        # print('拆包后:', **kwargs)       # 字典拆包后不能直接打印,会报错
        # 拆包后:MrLi='12231@qq.com', MsZhao='33371712@163.com', MasterHe='938722@qq.com'
        person(**kwargs)
    
    
    
    out_mail(MrLi='12231@qq.com', MsZhao='33371712@163.com', MasterHe='938722@qq.com')
    
    # -----输出结果-----
    拆包前: {'MrLi': '12231@qq.com', 'MsZhao': '33371712@163.com', 'MasterHe': '938722@qq.com'}
    12231@qq.com
    33371712@163.com
    938722@qq.com
    
    • 梳理一下
    def person(MrLi, MsZhao, MasterHe):
        print(MrLi)
        print(MsZhao)
        print(MasterHe)
    
    
    def out_mail(**kwargs):
        print('拆包前:', kwargs)
        # 拆包操作,元组拆包,通过一个星号 *
        # print('拆包后:', **kwargs)       # 字典拆包后不能直接打印,会报错
        # 拆包后:MrLi='12231@qq.com', MsZhao='33371712@163.com', MasterHe='938722@qq.com'
        # person(**kwargs)
        # 上面的**kwargs拆包,相当于将字典中的键值对拆包成关键参数传入person函数中
        person(MrLi='12231@qq.com',MsZhao='33371712@163.com',MasterHe='938722@qq.com')
    
    
    out_mail(MrLi='12231@qq.com', MsZhao='33371712@163.com', MasterHe='938722@qq.com')
    
    # -----输出结果-----
    拆包前: {'MrLi': '12231@qq.com', 'MsZhao': '33371712@163.com', 'MasterHe': '938722@qq.com'}
    12231@qq.com
    33371712@163.com
    938722@qq.com
    
  • 特别注意
  • 函数中的拆包和之前我们学数据类型时候讲到的拆包还是有一点点的区别
  • 列表、元组、集合拆包
    l = [1, 2, 3]
    t = (4, 5, 6)
    s = (7, 8, 9)
    
    a, b, c = l
    d, e, f = t
    g, h, i = s
    
    print(a, b, c, d, e, f, g, h, i)
    
    
    def test(*args):
        print(args)
    
    print('不拆包传入')
    test(l)
    test(t)
    test(s)
    
    print('拆包传入')
    test(*l)
    test(*t)
    test(*s)
    
    
    # -----输出结果-----
    1 2 3 4 5 6 7 8 9
    不拆包传入
    ([1, 2, 3],)
    ((4, 5, 6),)
    ((7, 8, 9),)
    拆包传入
    (1, 2, 3)
    (4, 5, 6)
    (7, 8, 9)
    
    
  • 字典拆包
    d = {'MrLi': '12231@qq.com', 'MsZhao': '33371712@163.com', 'MasterHe': '938722@qq.com'}
    
    a, b, c = d
    
    print(a, b, c)      # 直接拆包,是将字典的key拆出来存入变量中
    
    
    def test(**kwargs):
        print(kwargs)
    
    
    # test(d)           # 直接传入字典报错:TypeError: test() takes 0 positional arguments but 1 was given
    
    test(**d)           # 函数中**拆包,是将字典拆分成key=value的关键参数
    

应用

  • 我们在程序中,读取到的数据一般都是用列表、元组、集合和字典类型进行存储,但是这些类型在传入这些不定长参数函数中时,并不能直接传入,所以在传入的时候需要通过*** 进行拆包
  • 示例1
    
    def mySum(*args):
        print(args)
        result = 0
        for num in args:
            result += num
        print(result)
    
    
    l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    # mySum(l)      # --> 直接传入列表报错
    
    # -----输出结果-----
    ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10],)
    Traceback (most recent call last):
      File "E:\Projecs\Python\11-函数\01-函数定义.py", line 291, in <module>
        mySum(l)      # --> 直接传入列表报错:TypeError: unsupported operand type(s) for +=: 'int' and 'list'
      File "E:\Projecs\Python\11-函数\01-函数定义.py", line 285, in mySum
        result += num
    TypeError: unsupported operand type(s) for +=: 'int' and 'list'
    
    
    mySum(*l)
    
    # -----输出结果-----
    (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    55
    
  • 示例2
    def out_mail(**kwargs: str):
        print(kwargs)
        for k, v in kwargs.items():
            print(f'{k}的邮箱是:{v}')
    
    
    d = {'MrLi': '12231@qq.com', 'MsZhao': '33371712@163.com', 'MasterHe': '938722@qq.com'}
    
    # out_mail(d)     # --> 直接传入字典,会报错
    
    # -----输出结果-----
    Traceback (most recent call last):
      File "E:\Projecs\Python\11-函数\01-函数定义.py", line 318, in <module>
        out_mail(d)     # --> 直接传入字典,会报错
    TypeError: out_mail() takes 0 positional arguments but 1 was given
    
    
    out_mail(**d)       # --> 传入的时候通过**进行拆包
    
    # -----输出结果-----
    {'MrLi': '12231@qq.com', 'MsZhao': '33371712@163.com', 'MasterHe': '938722@qq.com'}
    MrLi的邮箱是:12231@qq.com
    MsZhao的邮箱是:33371712@163.com
    MasterHe的邮箱是:938722@qq.com
    
    
    # 分析
    1. out_mail(**d) 中的 **d 相当于将字典d 拆包成了
        MrLi='12231@qq.com', MsZhao='33371712@163.com', MasterHe='938722@qq.com'
    2. 然后再讲这些值传入函数中
        out_mail(MrLi='12231@qq.com', MsZhao='33371712@163.com', MasterHe='938722@qq.com') 
    
    

参数传递分类

  • 在编程语言中,参数传递分为:值传递引用传递

    • 值传递:是指传递过来的 一个数据的副本,修改副本对源数据没有任何影响
      在这里插入图片描述

      • 如图:修改num,实际是通过新的内存地址找到新的数值进行修改,源数据不改变
    • 引用传递:是指传递过来的是一个变量的地址,通过地址可以操作同一份源数据
      在这里插入图片描述

      • 如图:修改num,实际是通过内存地址找到源数据进行修改,源数据会改变
  • 在python中,只有引用传递(地址传递)

    • 如果数据类型是可变类型(列表、集合、字典),则可以改变源数据
    • 如果数据类型是不可变类型(数字型、字符串、元祖),则不可以改变源数据
  • 示例1

    def func(num):
        print('num修改前:', num, id(num))
        print()
        num = 100
    
        print('num修改后:', num, id(num))
    
    
    b = 10
    print('函数调用前b:', b, id(b))
    func(b)
    print('函数调用后b:', b, id(b))
    
    # -----输出结果-----
    函数调用前b: 10 2161532627536
    num修改前: 10 2161532627536
    
    num修改后: 100 2161532818896
    函数调用后b: 10 2161532627536
    
    • 从输出结果可以看出来
      • 1、num修改之前,num的id与源数据b的id是一致的,说明是引用传递
      • 2、num修改之后,num的id发生改变值也发生了改变,单源数据的id没有发生改变值也没有发生改变
        在这里插入图片描述
  • 示例2

    def func(num):
        print('num修改前:', num, id(num))
        print()
        num[0] = 100
    
        print('num修改后:', num, id(num))
    
    
    l = [1, 2, 3]
    
    print('函数调用前l:', l, id(l))
    func(l)
    print('函数调用后l:', l, id(l))
    
    # -----输出结果-----
    函数调用前l: [1, 2, 3] 3177112963328
    num修改前: [1, 2, 3] 3177112963328
    
    num修改后: [100, 2, 3] 3177112963328
    函数调用后l: [100, 2, 3] 3177112963328
    
    • 从输出结果可以看出来
      • 1、num修改之前,num的id与源数据b的id是一致的,说明是引用传递
      • 2、num修改之后,num的id没有发生改变值发生了改变,源数据的id没有发生改变值也发生了改变
        在这里插入图片描述

返回值(return)

概念

  • 函数外部的代码想要获得函数执行的结果,就可以在函数里用return语句把结果返回
  • 注意:
    • 函数在执行过程中要遇到return语句,就会停止执行并返回结果,也可以理解为return语句代表着函数的结束
    • 如果在函数中没有指定return,那么这个函数的返回值为None
    • 函数在返回多个值的时候用“,”连接,返回值默认为一个元组
  • 示例
    # 没有返回值,直接将结果输出到控制台
    def mySum1(a: int, b: int):
        result = a + b
        print(result)
    
    
    r1 = mySum1(1, 2)             # --> 3
    print('r1:', r1)            # --> r1: None
    
    
    # 有一个返回值,调用函数时候可以用变量接收返回值
    def mySum2(a: int, b: int):
        result = a + b
        return result
    
    
    r2 = mySum2(1, 2)                # --> 不会直接输出结果,需要通过变量接收返回值结果
    print('r2:', r2)                # --> r2: 3
    
    
    # 多个返回值,通过“,”进行分隔,默认返回一个元组
    def calculate(a:int,b:int):
        he = a + b
        cha = a - b
    
        return he, cha
    
    
    result = calculate(5, 3)        # --> 不会直接输出结果,需要通过变量接收返回值结果
    print(result)                   # --> (8, 2),返回一个元组,可以通过索引获取元组内的元素值
    
    
    # 也可以直接用拆包方式接收结果
    h, c = calculate(5, 3)
    print(h)                        # --> 8
    print(c)                        # --> 2
    

函数的注释

  • 参数注释:用来说明参数的类型和约束

    • 通常在参数后面加冒号来表示参数的注释,如果参数有默认值,注解放在参数名和=号之间
    • 在函数调用的时候会有提示
    def mySum2(a: int, b: int, c: int = 10) -> int:
        result = a + b + c
        return result
    
    
    c = mySum2(1, 3, 5)
    

    在这里插入图片描述

  • 返回值注释:用来描述返回值的一些说明

    • 通常在函数末尾的):之间添加->和注解表达式,来对返回值添加注释说明
    • 需要进入函数内部(在函数调用时,按住Ctrl键点击函数)才能看到注释说明
    def mySum2(a: int, b: int, c: 'int>10' = 10) -> int:
        result = a + b + c
        return result
    
    
    c = mySum2(1, 2, 15)
    

    在这里插入图片描述

  • 函数注释:又称为函数描述文档,在函数定义时对函数功能、参数、返回值等进行描述的注释

    • 通常使用三引号(即三个连续的单引号或双引号)来表示函数注释,一般放在函数的开头
    def mySum2(a: int, b: int, c: int = 10) -> int:
        """
        对传入的数据进行加法运算,并返回计算结果
        :param a: 整型数据
        :param b: 整型数据
        :param c: 整型数据
        :return: 返回a+b+c的计算结果
        """
        result = a + b + c
        return result
    
    
    c = mySum2(1, 3, 5)
    

    在这里插入图片描述

  • 我们可以通过help()函数获取函数的所有帮助信息

    help(mySum2)
    

    在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失心疯_2023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值