• 中文
    • English
  • 注册
  • 查看作者
  • 第十章:函数的参数和递归函数

    一、函数的参数

    1. 默认参数

    函数的默认参数有以下要求:

    • 必选参数在前,默认参数在后 (例1)

    • 当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。可以只传入变化大的参数,变化小的参数就可以作为默认参数(例2)

    • 当函数有多个参数时,可以单独调用函数时指定某个参数(例2)

    • 默认参数必须指向不变对象(例3)

    # 例1
    def pow(x, n=2):
        s = 1
        while n > 0:
            n -= 1
            s *= x
        return s
    
    print(pow(5,3)) #125
    print(pow(5)) #25
    
    # 例2
    def addStudents(name,age=18,sex="保密"):
        print(f"姓名= {name},年龄 = {age},性别 = {sex}")
    
    addStudents("张甲")  # 姓名= 张甲,年龄 = 18,性别 = 保密
    addStudents("张甲",22) #姓名= 张甲,年龄 = 22,性别 = 保密
    addStudents("张甲",sex="男") #姓名= 张甲,年龄 = 18,性别 = 男
    
    # 例3
    def add_end(L=[],M=None):
        L.append('END')
        if M is None:
            M = []
            M.append("END")
        return L,M
    
    print(add_end()) #(['END'], ['END'])
    print(add_end()) # (['END', 'END'], ['END'])

    2. 可变参数

    可变参数只需要在参数前添加一个*即可,在函数内部,参数接收到的是一个tuple

    def total(*num):
        sum = 0
        for i in num:
            sum += i
        return sum
    
    print(total()) #0
    print(total(1,2,3)) #6
    nums = [1,2,3,4]
    print(total(*nums)) #传入list,结果为10

    3. 关键字参数

    在函数内部,参数接收到的是一个dict,该dict是对参数的一份拷贝,对参数的改动不会影响到函数外的参数值。

    def persion(**kw):
        kw['sex'] = '保密'
        print(kw)
    
    
    persion(city='RiZhao', age=20)  # {'city': 'RiZhao', 'age': 20}
    
    per = {'name': 'ZhangJia', 'sex': '男'}
    
    persion(**per)  #{'name': 'ZhangJia', 'sex': '保密'}
    print(per)  # {'name': 'ZhangJia', 'sex': '男'} 不会影响per的值

    4. 命名关键字参数

    如果要限制关键字参数的名字,可以用命名关键字参数

    • 命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数

    • 命名关键字参数必须传入参数名(例1)

    • 如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了 (例2)

    • 命名关键字参数可以有缺省值,从而简化调用(例3)

    #例1
    def person(name, age, *, city, job):
        print(name, age, city, job)
    person("ZhangJia",18,"日照","银行工作者")  #报错
    person("ZhangJia",18)  #报错 
    
    person("ZhangJia",18,city="日照",job = "银行工作者") #ZhangJia 18 日照 银行工作者
    
    #例2
    def person(name, age, *args, city, job):
        print(name, age, city, job)
    
    #person("ZhangJia",18,"日照","银行工作者")  #报错
    #person("ZhangJia",18)
    person("ZhangJia",18,city="日照",job = "银行工作者") #ZhangJia 18 日照 银行工作者
    
    
    #例3
    def person(name, age, *, city="日照", job):
        print(name, age, city, job)
    
    person("ZhangJia",18,job = "银行工作者") #ZhangJia 18 日照 银行工作者

    5. 参数组合

    在Python中定义函数时,必选参数、默认参数、可变参数、命名关键字参数、关键字参数这5种参数可以组合使用。

    • 参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

    • 对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的,*args表示任何多个无名参数,它是一个tuple;**kwargs表示关键字参数,它是一个dict。同时使用*args和**kwargs时,必须*args参数列要在**kwargs前

    6. 练习

    定义一个函数可接收一个或多个数并计算乘积:

    #方法1
    def mul(*x):
        if len(x) == 0:
            raise TypeError
        y = 1
        for i in x:
          y *= i
        return y
        
     #方法2
    def mul(x,*y):
        for i in y:
            x *= i
        return x

    二、递归函数

    一个函数在内部调用自身本身,这个函数就是递归函数。

    练习:计算阶乘n! = 1 x 2 x 3 x … x n,用函数fact(n)表示,fact(n)可以表示为n x fact(n-1),n=1时,返回1

    def fact(n):
        if n == 1:
            return 1
        return n * fact(n - 1)

    值得注意的是,使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

    解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。

    尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

    参考资料

    [1] 廖雪峰-Python教程

  • 0
  • 1
  • 0
  • 1.4k
  • 请登录之后再进行评论

    登录
  • 0
    你好,能求一份数据库的表吗
  • 单栏布局 侧栏位置: