• Python函数


    函数的概念

    编程中的函数,是一段可以被重复使用的代码片段,使用函数能够减少冗余的代码。比如:

    # 1.求1-100的和
    sum = 0
    for i in range(1, 101):
        sum += i
    print(f'sum = {sum}')  # 5050
    
    # 2.求300-400的和
    sum = 0
    for i in range(300, 401):
        sum += i
    print(f'sum = {sum}')  # 35350
    
    # 3.求1-1000的和
    sum = 0
    for i in range(1, 1001):
        sum += i
    print(f'sum = {sum}')  # 500500
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    上述几组代码的处理逻辑都是类似的,这种情况就可以把重复的代码提取出来,封装成一个函数,需要求和时直接调用该函数即可。比如:

    def calcSum(begin, end):
        theSum = 0
        for i in range(begin, end + 1):
            theSum += i
        return theSum
    
    
    print(calcSum(1, 100))    # 5050
    print(calcSum(300, 400))  # 35350
    print(calcSum(1, 1000))   # 500500
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这时就可以明显看到,重复的代码已经被消除了。

    函数的定义格式

    函数的定义格式

    函数的定义格式如下:
    在这里插入图片描述
    注意事项:

    • 一个函数可以有一个或多个形参,也可以没有形参。
    • 一个函数中可以有一个或多个return语句,执行到return语句时函数会立即执行结束,回到调用位置。
    • Python是动态类型语言,函数的形参和返回值都不必指定类型,因此一个函数可以支持多种不同类型的参数。

    多个返回值

    此外,Python中的一个函数可以有一个或多个返回值,当有多个值需要返回时,使用,来分隔这多个返回值。比如:

    def getSumAndDif(x, y):
        return x + y, x - y
    
    
    a = 10
    b = 20
    sum, dif = getSumAndDif(a, b)
    print(f'{a} + {b} = {sum}, {a} - {b} = {dif}')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Python中一个函数能返回多个值,本质就是多元赋值所支持的。如果函数调用者只想关注该函数的部分返回值,那么可以使用_来忽略不想要的返回值。比如:

    _, dif = getSumAndDif(1, 2)
    print(dif)
    
    • 1
    • 2

    函数的调用格式

    函数的调用格式

    函数的调用格式如下:
    在这里插入图片描述
    注意事项:

    • 函数必须先定义再使用,函数定义后并不会执行函数体的内容,必须要被调用后才会执行。

    传参方式

    调用函数时可以根据函数的形参列表,将实参列表中的实参按照顺序依次传给对应的形参。比如:

    def Dif(x, y):
        return x - y
    
    
    print(Dif(10, 20))  # -10
    
    • 1
    • 2
    • 3
    • 4
    • 5

    此外,也可以通过关键字参数来调整传参的顺序,显式指定当前实参传递给哪个形参。比如:

    print(Dif(y=10, x=20))  # 10
    
    • 1

    函数的调用方式

    链式调用

    链式调用指的是把一个函数的返回值,作为调用另一个函数时的参数进行传入。

    例如,下面代码中调用print函数时,将Add函数的返回值作为了参数。

    def Add(x, y):
        return x + y
    
    
    print(Add(10, 20))  # 30
    
    • 1
    • 2
    • 3
    • 4
    • 5

    嵌套调用

    嵌套调用指的是在一个函数的函数体内部,调用了其他函数。

    例如,下面代码中的test函数内部调用了print函数。

    def test():
        print('do something...')
        print('do something...')
        print('do something...')
    
    
    test()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    递归调用

    递归掉是嵌套调用的一种特殊情况,即在一个函数内部嵌套调用自己。

    例如,下面的factor函数可以用来求一个数的阶乘

    def factor(n):
        if n == 1:
            return 1
        return n * factor(n - 1)
    
    • 1
    • 2
    • 3
    • 4

    在factor函数内部又嵌套调用了factor函数,这就是递归调用。

    递归调用与返回的过程

    以求3的阶乘为例,factor函数的递归调用与返回过程如下图:
    在这里插入图片描述
    即一层层进行递归调用,当满足递归结束条件时再逐层进行返回。

    递归的两个条件

    需要注意的是,递归必须满足以下两个条件:

    1. 存在递归结束条件。
    2. 每进行一次递归,都会逐渐逼近结束条件。

    以上述的factor函数为例,其递归结束条件就是if语句中的n == 1,当n为1的时候递归就结束了,而每次递归调用factor函数时传入的参数都是n - 1,因此每进行一次递归n的值都会逐渐逼近1。如果不能满足这两个条件,就会出现无限递归,最终导致栈溢出(Stack Overflow)。

    说明一下: 函数调用时会在函数调用栈中记录每一层函数调用的信息,但函数调用栈的空间不是无限大的,如果函数调用层数太多,就会超出栈的最大范围,进而导致栈溢出。

    递归的优缺点

    递归的优点:

    • 递归类似于“数学归纳法”,明确初始条件,和递推公式,就可以解决一系列的问题。
    • 递归代码往往代码量非常少。

    递归的缺点:

    • 递归代码往往难以理解,很容易超出掌控范围。
    • 递归代码容易出现栈溢出的情况。
    • 递归代码往往可以转换成等价的循环代码,并且通常来说循环版本的代码执行效率要略高于递归版本,因为函数的调用也是需要开销的。

    默认参数与变长参数

    默认参数

    可以给函数的形参指定默认值,在调用函数时可以不必给带有默认值的形参传参,此时该形参将会使用我们指定的默认值。

    例如,下面调用Add函数时如果不传入第二个参数,则默认返回第一个参数与1的和,如果调用Add函数时传入了第二个参数,则返回这两个参数的和。

    def Add(data, val=1):
        return data + val
    
    
    print(Add(10))     # 11
    print(Add(10, 2))  # 12
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意: 在定义函数时,带有默认值的参数需要放到没有默认值的参数后面。

    变长参数

    如果想让函数接收任意个数的参数,可以在函数定义的形参名称前面添加*,这时函数将接收一个参数元组,并且我们可以以形参名[下标]的方式相应地访问传入的各个实参。比如:

    def Func(*arg):
        n = len(arg)
        for i in range(n):
            print(arg[i])
    
    
    Func(1)
    Func(1, 2, 3)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    说明一下: 元组是Python中的一个数据类型,本文先不做介绍。

    变量作用域

    变量的作用域

    每一个变量都有自己的作用域:

    • 定义在函数内部的变量,其作用域仅在该函数内部,称为“局部变量”。
    • 定义在函数外部的变量,其作用域是全局的,称为“全局变量”。

    注意事项:

    • 变量只能在自己所在的函数内部生效。
    • 在不同的作用域中,允许存在同名的变量。

    函数中操作全局变量

    需要注意的是,如果在函数内部尝试访问的变量在局部不存在,就会尝试去全局域中查找。比如:

    x = 10
    
    def Func():
        print(f'x = {x}')
    
    Func()  # x = 10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    但如果想要在函数内部修改全局变量的值,就需要使用global关键字进行声明。比如:

    x = 10
    
    def Func():
        global x  # 声明
        x = 20
        print(f'函数内部: x = {x}')  # x = 20
    
    Func()
    print(f'函数外部: x = {x}')  # x = 20
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如果在函数内部修改全局变量时没有用global关键字进行声明,那么此时Python解释器会认为你是想在函数内部创建一个同名的局部变量,此时你的修改操作就不会影响到对应的全局变量。比如:

    x = 10
    
    def Func():
        # global x
        x = 20
        print(f'函数内部: x = {x}')  # x = 20
    
    Func()
    print(f'函数外部: x = {x}')  # x = 10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    if、while、for中的变量

    Python中的if、while、for等语句块不会影响变量的作用域,因此在这些语句块中定义的变量,也能在外面正常使用。比如:

    for i in range(10):
        print(f'函数内部: i = {i}')
    
    print(f'函数外部: i = {i}')  # i = 9
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    C++之this指针
    imx6ull移植openwrt
    基于TCP的聊天系统
    PCB如何入门---一些经验与教训
    Docker-06:仓库
    网络编程:基于TCP和UDP的服务器、客户端
    和百度AI探讨“存在者存在”哲学问题
    Hugging Face 与 Wiz Research 合作提高人工智能安全性
    浙江某华智能停车综合管理系统未授权访问漏洞复现 CNVD-C-2023-517991
    擦除编码(EC)数据中心中的最优机架协调更新
  • 原文地址:https://blog.csdn.net/chenlong_cxy/article/details/127551232