• 中文
    • 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.2k
    • 请登录之后再进行评论

      登录
    • 0
      你好,能求一份数据库的表吗
    • 赞助本站

      • 支付宝
      • 微信
      • QQ

      感谢一直支持本站的所有人!

      单栏布局 侧栏位置: