• python函数基础


    python函数

    • 函数的基本定义
    • 函数参数
    • 返回值
    • 局部变量和全局变量
    • 嵌套函数
    • 匿名函数
    • 高阶函数
    • 递归

    函数的基本定义

    引子

    现在你的老板让你写一个监控程序,24小时全年午无休的监控你们公司网站服务器的运行状况,当cpumemorydisk等指标的使用量超过阈值时即发送报警邮件:

    while True:
        if cpu利用率 > 90%:
            #发送邮件提醒
            连接邮箱服务器
            发送邮件
            关闭连接
    
        if 硬盘使用空间 > 90%:
            #发送邮件提醒
            连接邮箱服务器
            发送邮件
            关闭连接
    
        if 内存占用 > 80%:
            #发送邮件提醒
            连接邮箱服务器
            发送邮件
            关闭连接
    

    那么当你的同事看到这个代码的时候,就发现了代码的重复性比较高,每次报警都要重写一段发邮件的代码,一个劲的copy and paste根本就不符合高端程序员的气质,其次如果以后想修改发邮件的代码,比如加上群发功能,那么就需要在所有代码上都要修改一遍.

    你也看出来了这个问题,你也不想去写重复代码,但又不知道怎么写,此时你的同时笑着和你说,这个很简单,只要把重复的代码提出出来,放在一个公共的地方,起个名字,以后谁想用这个代码,就通过这个名字就可以调用了.,如下:

    def 发送邮件(内容):
        # 发送邮件提醒
        连接邮件服务器
        发送邮件
        关闭连接
    
    while True:
        if cpu利用率 > 90%:
            发送邮件('CPU报警')
        if 硬盘使用空间 > 90%:
            发送邮件('硬盘报警')
        if 内存占用 > 80%:
            发送邮件('内存报警')
    

    基本定义

    函数是什么?

    函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,编程中的函数在英文中也有很多不同的叫法。在BASIC中叫做subroutine(子过程或子程序),在Pascal中叫做procedure(过程)和function,在C中只有function,在Java里面叫做method。

    定义:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可

    函数的特征

    • 减少重复代码
    • 使程序变得可扩展
    • 使程序变得可维护

    语法定义

    def sayhi():  # sayhi函数名
        print('hello world')
    
    sayhi()  # 调用函数
    

    函数参数

    形参变量
    只有在调用时猜分配内存单元,在调用结束后,即刻释放所分配的内存单元.因此,形参只在函数内部有效.函数调用结束返回主调用函数后则不能再使用该形参变量

    实参
    可以是常量变量表达式函数等,无论实参是那种类型的量,再进行函数调用时,他们都必须有确定的值,以便把这些值传送给形参.因此应预先用赋值,输入等方法使参数获得确定值.

    def cacl(x,y):  # 此时的x,y是形参
        res = x**y
        return res
    
    c = cacl(2,5)  # 此时的2,5是形参
    print(c)
    

    默认参数

    看如下代码:

    def stu_register(name,age,country,course):
        print('-----注册学生信息-----')
        print('姓名:',name)
        print('年龄:',age)
        print('国家:',country)
        print('课程:',course)
    
    stu_register('老王',22,'CHINA','PYTHON')
    stu_register('小明',18,'CHINA','JAVA')
    stu_register('康康',19,'CHINA','C++')
    

    运行结果如下:

    -----注册学生信息-----
    姓名: 老王
    年龄: 22
    国家: CHINA
    课程: PYTHON
    -----注册学生信息-----
    姓名: 小明
    年龄: 18
    国家: CHINA
    课程: JAVA
    -----注册学生信息-----
    姓名: 康康
    年龄: 19
    国家: CHINA
    课程: C++
    

    这时候我们发现了一个问题,我们发现country这个参数的值都是CHINA,就像我们在注册网站的时候,像国家这种信息,你不填写的话,那么默认是CHINA,这就是通过默认参数实现的,把country变成默认参数非常简单.

    def stu_register(name,age,course,country='CHINA'):
    

    这样,这个参数在调用时不指定,那么默认就是CHINA了,如果指定的话,就是你自己指定的值了.举个例子看看:

    # 默认参数--如果用户指定了参数值,则使用用户指定的值,否则使用默认参数的值。
    def stu_register(name,age,course,country='CHINA',):
        print('-----注册学生信息-----')
        print('姓名:',name)
        print('年龄:',age)
        print('国家:',country)
        print('课程:',course)
    
    stu_register('老王',22,'PYTHON')
    stu_register('小明',18,'JAVA','JAPAN')  # 指定了country = JAPAN
    

    那么我们看一下运行结果:

    -----注册学生信息-----
    姓名: 老王
    年龄: 22
    国家: CHINA
    课程: PYTHON
    -----注册学生信息-----
    姓名: 小明
    年龄: 18
    国家: JAPAN
    课程: JAVA
    

    那么,为什么默认参数要放置在参数的最后一个位置呢?让我们来看下:

    def stu_register(name,age,country='CHINA',course):  # 如果写成这样的话,那么会立即报错,根本就不会运行,因为将实参传递给形参时,不知道CHINA是传给谁的
        print('-----注册学生信息-----')
        print('姓名:',name)
        print('年龄:',age)
        print('国家:',country)
        print('课程:',course)
    
    stu_register('康康',19,'CHINA','C++')
    

    关键参数

    正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名就可以了(指定参数名的参数就叫做关键参数),注意:关键参数必须放在位置参数之后(以位置顺序确定对应关系的参数)
    举个例子看一下:

    def stu_register(name,age,course='python',country='CHINA'):  # 设置两个默认参数
        print('-----注册学生信息-----')
        print('姓名:',name)
        print('年龄:',age)
        print('国家:',country)
        print('课程:',course)
    
    stu_register('王佳',course='LIUNX',age = 22)
    

    但是不可以这样调用:

    stu_register('小明',course='java ',22,country='JAPAN')
    也不可以这样
    stu_register('小明',22,23,country='JAPAN')  # 这句话等于将22 23传递给了age,但是不能传递两个值
    

    非固定参数

    若你的函数中不确定要传入多少参数,就可以使用非固定函数,举个例子来说,文章开头的邮件报警,现在我不想只对一个人发邮件,我想对整个运维部的人发送报警邮件,那么这个时候使用非固定参数最合适不过了:

    def students(name,age,*args):  # *args 会把多传入的参数变成一个元组形式
        print(name,age,args)  # 打印name,age,args
    
    students('小明',22,'PYTHON','CHINA')  # 小明 22 ('PYTHON', 'CHINA')
    

    原来,*args所接受的参数是用元组的形式保存的

    那么现在还有一个**kwargs

    def stu(name,age,*args,**kwargs):
        print(name,age,args,kwargs)
    
    stu('肖亚飞',22)  # 肖亚飞 22 () {}
    # 让我们看看args和kwargs的差别在哪?
    stu('肖爸爸',23,'python','linux')  # 肖爸爸 23 ('python', 'linux') {}
    stu('肖爸爸',23,'python','linux',addr = 'Henan',music = '蝴蝶')  # 肖爸爸 23 ('python', 'linux') {'addr': 'Henan', 'music': '蝴蝶'}
    

    总结:

       1.*args必须放在**kwargs之前
       2.*args 没有key值,**kwargs有key值
       3.使用*args和**kwargs可以非常方便的定义函数,同时可以加强扩展性,以便日后的代码维护 
    

    返回值

    函数外部的代码想要获取函数的执行结果,就可以在函数里使用return语句把结果返回

    def student(name,age,course='PYTHON',country='CN'):  # 设置了course和country两个默认参数
        print('-----注册学生信息-----')
        print('姓名:',name)
        print('年龄:',age)
        print('国家:',country)
        print('课程:',course)
    
        if age > 20:  # 判断如果age大于20
            return False  # 返回False
        else:
            return True
    
    result = student('张三',22)  # 函数外部的代码想要获取函数的执行结果,就需要使用一个变量来进行接受
    if result:  # 如果result = True
        print('恭喜注册成功!')
    else:  # 如果result = Flase
        print('年纪太大!')
    

    看一下运行结果:

    -----注册学生信息-----
    姓名: 张三
    年龄: 22
    国家: CN
    课程: PYTHON
    年纪太大!   
    

    注意

    • 函数在执行过程中,只要遇到return语句,就会停止执行并返回结果,so也可以理解为return语句代表着函数的结束
    • 如果未在函数中指定return,那么这个函数的返回值为None

    局部变量和全局变量

    
    name = 'xiaoyafei'
    def change_name(name):  # 定义一个函数,传递Name参数
        print('修改前:',name)
        name = '肖亚飞'
        print('修改后:',name)
    
    change_name(name)
    print('在外面看修改过了吗?',name)
    

    输出结果为:

    修改前: xiaoyafei  # 没修改之前的
    修改后: 肖亚飞  # 在函数里修改过的
    在外面看修改过了吗? xiaoyafei  
    

    不用传name参数,在函数里面还是可以调用外面的变量

    name = "xiaoyafei"
    def change_name():
        name = '肖亚飞'
        print("修改后:",name)
    change_name()
    print("在外面看:",name)
    

    运行结果为:

    修改后: 肖亚飞
    在外面看: xiaoyafei
    

    那么,为啥我明明修改过了,为啥在外面还是没修改呢?让我们看看name变量的空间地址:

    name = "xiaoyafei"
    def change_name():
        name = '肖亚飞'
        print("函数内,id:",id(name))
    change_name()
    print("函数外,id:",id(name))
    

    结果如下:

    函数内,id: 1388194004688
    函数外,id: 1388193784688
    

    要是不放大你的眼睛还真的看不清楚呢,内存空间地址不同,所以两个name是没有关系的,那么为啥一个函数里能定义两个甚至更多相同的变量呢?

    • 在函数中定义的变量称为全局变量,在程序的一开始定义的变量称为全局变量
    • 全局变量的作用域是整个程序,局部变量的作用是定义该变量的函数
    • 当全局变量和局部变量相同时,在定义局部变量的函数内,局部变量起作用;在其他地方全局变量起作用

    作用域

    作用域,程序设计概念,通常来说,一段代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用与.

    如何在函数里修改全局变量

    name = '肖亚飞'
    
    def change_name():
        global name  # global的作用就是在函数里声明全局变量name,意味着最上面的name = '肖亚飞'即使不写,程序最后面也可以print name
        name = 'xiaoyafei'
        print('函数里修改:',name)
    
    change_name()  # 调用函数
    print('函数外:',name )
    

    运行结果如下:

    函数里修改: xiaoyafei
    函数外: xiaoyafei
    

    嵌套函数

    
    name = 'xiaoyafei'
    def change_name():
        name = 'xiaoyafei2'
    
        def change_name2():
            name = 'xiaoyafei3'  # 如果在当前函数拥有name变量,则使用函数内的name变量,如果没有,则会去上一级去找name,一直找到全局变量
            print('第3层打印:',name)  # 第3层打印: xiaoyafei3
    
        change_name2()
        print('第2层的音:',name)  # 第2层的音: xiaoyafei2
    
    change_name()
    print('第一层打印:',name)  # 第一层打印: xiaoyafei
    

    匿名函数

    匿名函数就是不需要显示的指定函数名

    匿名函数的声明

    res1 = lambda x,y:x+y  #声明一个匿名函数,有x和y两个参数,操作为x+y
    print(res1)  # <function <lambda> at 0x0000021D32590D08>
    

    常规函数和匿名函数:

    # 常规函数
    def cacl(x,y):
        return x**y
    
    res = cacl(2,3)  # 如果想要使用函数的返回值,就需要定义一个变量来接收
    print(res)  # 8
    
    # 匿名函数
    res = lambda x,y:x**y
    print(res(2,3))  # 8
    
    

    匿名函数的优点:

    • 使用python写一些脚本时,使用lambda可以省去自定义函数的过程,让代码更加精简
    • 对于一些抽象的,不会被别的地方再重复使用的函数,有时候函数起个名字也是个难题,使用lambda不用考虑这些问题
    • 使用lambda在某些时候让代码更容易理解

    匿名函数的其余用法

    data  = list(range(10))
    print(data)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    # 问题:用两种方法计算这些数的平方
    
    # 常规操作
    for index,i in enumerate(data):
        data[i] = i*i
    print(data)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    
    # 装逼操作
    res = list(map(lambda x:x*x,data))
    print(res)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    

    那么在方法2中的map()函数是啥意思?

    map()会根据提供的函数对指定序列做映射

    第一个参数functrion以参数序列中的每一个元素调用function函数,返回包含每次function函数返回值的新列表,可以不懂,下面就会讲,

    今天不是看到map()函数,我还真不知道python2和python3中的map()有区别,让我们举个例子看一下map()函数的用法:

    在python2中:
    >>> def cacl(x):  # 求一个数的平方
    ...     return x**2
    ...
    >>> map(cacl,[1,2,3,4,5])  # 在python2中返回的是列表
    [1, 4, 9, 16, 25]
    >>>
    
    在python3中:
    >>> def cacl(x):
    ...     return x**2
    ...
    >>> map(cacl,[1,2,3,4,5])  # python3中返回的是迭代器对象,何谓迭代器?晚点会在博客中说明
    <map object at 0x0000015B373533C8>
    >>> res = map(cacl,[1,2,3,4,5])
    >>> next(res)  # 返回迭代器中的下一个值
    1
    >>> next(res)
    4
    

    map()函数在python2和python3中的区别:

    • 在python2中返回的是列表
    • 在python3中返回的是迭代器对象

    map()是python内置的高阶函数,它接收一个函数cacl和一个list,并通过函数cacl依次作用于list的每个元素上,并且得到一个新的list并返回,由于list包含的元素可以是各种类型的,因此,map()不仅仅可以处理只包含数值的list,事实上它也可以处理包含任意类型的list,只要传入的函数cacl可以处理这种数据类型.

    高级函数

    变量可以指向函数,函数的参数能接受变量,那么一个函数就可以接收另一个函数作为参数,这种函数就被称为高阶函数.

    • 接收一个或多个函数作为输入
    • return 返回另外一个函数
    def func2(x,y):
        return abs,x,y
    res = func2(-1,10)
    print(res)  # (<built-in function abs>, -1, 10)
    
    def cacl(x,y,f):
        return f(x)+f(y)
    
    res = cacl(-4,10,abs)
    print(res)  # 14
    
    
  • 相关阅读:
    maven项目,去除jar包中的不想要的依赖关系
    Eclipse:An internal error occurred during: "Build Project". GC overhead limit exceeded
    如何用Maven创建web项目(具体步骤)
    让Jackson JSON生成的数据包含的中文以unicode方式编码
    MySQL存储过程详解 mysql 存储过程
    MySQL SQL Injection(注入)
    撤销Excel工作表保护密码(考勤机报表)
    youtube-dl下载视频
    LSI9240 8i在dos下刷IT直通模式
    制作DOS引导U盘(支持扩展任何dos下的程序)
  • 原文地址:https://www.cnblogs.com/xiaoyafei/p/8986960.html
Copyright © 2020-2023  润新知