python源码中的学习笔记_第8章_函数

本文详细介绍了Python函数的创建、调用、参数传递方式,包括位置参数、关键字参数、默认值、可变参数以及递归函数。同时,讨论了函数参数传递对实参的影响,特别是对于可变对象的特殊情况。还涵盖了异常处理机制,展示了如何通过try-except来优雅地处理程序中的错误。此外,文章还提到了变量的作用域,以及不同类型的函数参数,如个数可变的位置形参和关键字形参。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数的创建与调用

#
# 主题:函数的创建与调用
#

if __name__ == '__main__':
    # 创建函数
    # 求解 a + b
    def calc(a, b):
        c = a + b
        return c

    # 调用函数
    result = calc(10, 20)
    print(result)               # 30

函数的参数传递

  • 位置传参
    在这里插入图片描述

  • 关键字传参
    在这里插入图片描述

#
# 主题:函数的参数传递
#

if __name__ == '__main__':
    # 位置传参
    # 求解 a + b
    def calc(a, b):     # a,b 是形式参数,简称形参,形参的位置是在函数的定义处
        c = a + b
        return c

    result = calc(10, 20)   # 10,20 是实际参数的值,简称实参,实参的位置是在函数的调用处
    print(result) # 30

    # 关键字传参
    result1 = calc(b = 10, a = 20)  # = 左边的变量名称为关键字参数
    print(result1)  # 30

函数的参数传递对实参的影响

#
# 主题:函数的参数传递对实参的影响
#

def fun(arg1, arg2):
    print('arg1 =', arg1)
    print('arg2 =', arg2)
    arg1 = 100
    arg2.append(10)
    print('arg1 =', arg1)
    print('arg2 =', arg2)

if __name__ == '__main__':
    n1 = 11
    n2 = [22, 33, 44]
    print(n1)           # 11
    print(n2)           # [22, 33, 44]
    print('---')
    fun(n1, n2)         # arg1 = 11
                        # arg2 = [22, 33, 44]
                        # arg1 = 100
                        # arg2 = [22, 33, 44, 10]
    print('---')
    print(n1)           # 11 只是值传递
    print(n2)           # [22, 33, 44, 10] 相当于C语言中在指针层面上的数据操作
    '''在函数调用过程中,进行参数的传递
        若是不可变对象,则在函数体中的修改不会影响实参的值
        若是可变对象,则在函数体的修改会影响实参的值'''

函数的返回值

#
# 主题:函数的返回值
#

def fun(num):
    odd = []            # 存奇数
    even = []           # 存偶数
    for i in num:
        if i % 2 == 1:
            odd.append(i)
        else:
            even.append(i)
    return odd, even

if __name__ == '__main__':
    print(fun([10, 29, 34, 23, 44, 53, 55]))        # ([29, 23, 53, 55], [10, 34, 44])

    # 若返回值有多个结果,则返回值的类型是元组

函数定义中的形参 —— 默认值

#
# 主题:函数定义中的形参 —— 默认值
#

def fun(a, b = 10):
    print(a, b)

if __name__ == '__main__':
    fun(100)                # 100 10    b未传参,采取默认值
    fun(20, 30)             # 20 30     30替换10

    # print函数也有默认值参数。在代码中,按住Ctrl不放,鼠标点击print函数名进入函数定义处
    print('hello')
    print('python')         # hello
                            # python
                            # print在字符串的末尾默认加'\n'

    print('hello', end = '\t')
    print('world')          # hello	  world

函数定义中的形参 —— 个数可变的位置形参

#
# 主题:函数定义中的形参 —— 个数可变的位置形参
#

def fun(*args):
    print(args)
   
def fun1(a, b, c):
    print('a =', a)
    print('b =', b)
    print('c =', c)   

if __name__ == '__main__':
    # 定义函数时,可能无法事先确定传递的位置实参的个数时,使用个数可变的位置参数
    # 使用一个*定义个数可变的位置形参
    # 函数的返回值类型是元组
    fun(10)                 	# (10,)
    fun(10, 'hello', True)  	# (10, 'hello', True)
    
    ''' def fun2(*args, *a):
        	pass
        以上代码,程序会报错,可变的位置参数,只能是1个'''

    lst = [11, 22, 33]
    fun1(*lst)          # 函数调用时,将列表中的每个元素都转换为位置实参传入
                        # a = 11
                        # b = 22
                        # c = 33

函数定义中的形参 —— 个数可变的关键字形参

#
# 主题:函数定义中的形参 —— 个数可变的关键字形参
#

def fun(**args):
    print(args)

def fun1(a, b, c):
    print('a =', a)
    print('b =', b)
    print('c =', c)

if __name__ == '__main__':
    # 定义参数时,可能无法事先确定传递的位置实参的个数,这时使用可变的关键字形参
    # 函数的返回值是字典
    fun(a = 10)
    fun(a = 10, b = 'hello', c = True)  # {'a': 10}
                                        # {'a': 10, 'b': 'hello', 'c': True}

函数定义中的形参 —— 个数可变的关键字形参

#
# 主题:函数定义中的形参 —— 个数可变的关键字形参
#

def fun(**args):
    print(args)

def fun1(a, b, c):
    print('a =', a)
    print('b =', b)
    print('c =', c)
    
def fun3(a, b, *, c, d):        # * 后面的参数,在函数调用时,只能采用关键字参数传递
    print('a =', a)
    print('b =', b)
    print('c =', c)
    print('d =', d)

if __name__ == '__main__':
    # 定义参数时,可能无法事先确定传递的位置实参的个数,这时使用可变的关键字形参
    # 函数的返回值是字典
    fun(a = 10)
    fun(a = 10, b = 'hello', c = True)  # {'a': 10}
                                        # {'a': 10, 'b': 'hello', 'c': True}

    ''' def fun2(**args, **argc):
        pass
        以上代码会报错,个数可变的关键字参数,只能是1个
    '''

	# 函数定义时,形参的顺序问题
    # 在定义函数时,个数可变的位置形参要放在个数可变的关键字形参之前
    def fun2(*args1, **arg2):
        pass
    def fun4(a, b, *, c, d, **args):
    	pass
    def fun5(a, b = 10, *args, **args2):
    	pass

    dic = {'a': 100, 'b': 200, 'c': 300}
    fun1(**dic)         # 函数调用时,将字典中每个元素都转换为关键字实参传入
                        # a = 100
                        # b = 200
                        # c = 300

    fun3(a = 10, b = 20, c = 30, d = 40)    # 关键字实参传递
                                            # a = 10
                                            # b = 20
                                            # c = 30
                                            # d = 40

    fun3(10, 20, c = 30, d = 40)            # 前两个参数采用位置实参传递,后两个参数采用关键字实参传递
                                            # a = 10
                                            # b = 20
                                            # c = 30
                                            # d = 40

变量的作用域

#
# 主题:变量的作用域
#


if __name__ == '__main__':
    # 局部变量
    # 在函数被定义并使用的变量,只在函数内部有效
    # 局部变量使用global声明,这个变量就会成为全局变量
    def fun(a, b):
        global d        # d原先是局部变量,经过global声明后变成全局变量
        c = a + b       # c是局部变量
                        # a,b是函数的形参,作用范围是函数内部,相当于局部变量
        d = c
        print(c)
    fun(1, 2)           # c
    print(d)            # c

    # 全局变量
    # 函数体外定义的变量,可作用与函数内外

递归函数

#
# 主题:递归函数
#

def fac(n):
    '''
    功能:计算阶乘
    参数:n        变量
    返回:n!       阶乘结果
    '''
    if n == 1:          # 递归终止条件
        return 1        # 1! = 1
    else:               # 递归调用
        return n * fac(n - 1)

def fib(n):
    '''
    功能:斐波那契数列
    参数:n        当前数字在数列中是第几个
    返回:         斐波那契数列
    '''
    if n == 1:
        return 1
    elif n ==2:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)

if __name__ == '__main__':
    # 递归函数在函数体内调用函数自身
    # 递归函数的组成部分:递归调用与递归终止条件
    # 递归函数的调用过程
        # 每递归调用一次函数,就会在占内存分配一个栈帧
        # 每执行一次函数,都会释放相应的空间
    # 递归的优缺点:
        # 优点:思路和代码简单
        # 缺点:占用内存多,效率低下

    # 计算阶乘
    print(fac(6))           # 720

    # 计算斐波那契数列中第6位上的数字
    print(fib(6))           # 8

    # 输出斐波那契数列前6位的数字
    for i in range(1, 7):
        print(fib(i), end = '\t')   # 1	1	2	3	5	8

在这里插入图片描述

bug 分类

#
# 主题:bug 分类
#

if __name__ == '__main__':
    # TypeError             数据类型错误
    # IndexError            索引错误
    # ZeroDivisionError     除以零
    # KeyError              键错误
    # ValueError            值错误
    # NameError             标识符错误
    # SyntaxError           语法错误

异常处理机制

#
# 主题:异常处理机制
#

if __name__ == '__main__':
    # try 结构
    # 当异常出现时,即时捕获,从而保证程序继续执行
    try:                        # 可能报错的代码
        n1 = int(input('请输入一个整数:'))
        n2 = int(input('请输入另一个整数:'))
        result = n1 / n2
        print('结果为:', result)
    except ZeroDivisionError:   # except 后面是错误类型。根据错误类型执行对应的代码
        print('除数不能为0哦!!!')
    except ValueError:
        print('请检查输入是否正确')
    except BaseException as e:  # 提取错误提示
                                # 正常报错是这样:ValueError: invalid literal for int() with base 10: ''
                                # 执行词句后,e = invalid literal for int() with base 10: ''
        print(e)
        print(type(e))          # <class 'ValueError'>  ValueError 是错误类型
    else:
        print('结果为:', result) # 若 try 块没有异常,则执行 else 块,否则执行 except 块
    finally:                    # 无论是否有异常,都会执行这块代码,常用于释放 try 块中申请的资源
        print('无论是否有异常,都会执行')

    # traceback 模块打印异常信息
    # 用于将异常信息存入到日志文件(log日志)里
    import traceback
    try:
        print('---')
        num = 10 / 0
    except:
        traceback.print_exc()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值