zoukankan      html  css  js  c++  java
  • 函数

    本节导读:

    • 函数的定义与特性
    • 函数的创建
    • 函数的参数
    • 函数的返回值
    •  函数的作用域(局部变量和全局变量)
    • 匿名函数
    • 函数的高级用法

    函数的定义与特性

    定义:

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

    特性:

    1. 减少重复代码
    2. 使程序变的可扩展
    3. 使程序变得易维护

    二 函数的创建与调用:

    # 创建函数
    def sayhi():
        print("Hello, I'm nobody!")
    # 调用函数
    sayhi() #在函数名后面加括号,就是调用这个函数

    三 函数的参数

    • 形参和实参

      形参:是函数定义时候定义的参数

      实参:函数调用的时候传进来的参数

    • 默认参数
      以下代码,country位置不填写,则默认为“CN”,country位置填写,则传入该值,默认参数后移动到最后
      def stu_register(name,age,course,country="CN"):
    • 关键参数

      正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定了参数名的参数就叫关键参数),但记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定对应关系的参数)之后

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

      调用可以这样

      stu_register("王山炮",course='PY', age=22,country='JP' )

      但绝不可以这

      stu_register("王山炮",course='PY',22,country='JP' )

      当然这样也不行

      stu_register("王山炮",22,age=25,country='JP' )

      这样相当于给age赋值2次,会报错!

    • 非固定参数
      函数在定义时不确定用户想传入多少个参数时,就可以使用非固定参数

      *arg

      send_alert(msg,*arg)# 会将多个值打包成一个元组,也可以传一个元组或列表,但是要记得在传的元组或列表前加*,否则或默认次列表,为外层元组中的一个元素
      send_alert(msg,*args,age)
      send_alert('alex','rain','eic',22) #会报错,alex后的全被*args截胡了,age得不到值
      send_alert('alex','rain','eic',age = 22) #这样才正确

      **kwarg

      def stu_register(name,age,*args,**kwargs): # *kwargs 会把传入的键值对形式,自动打包成字典,也可以传字典,但是得在前面加**
         print(name,age,args,kwargs) stu_register("Alex",22) #输出 #Alex 22 () {}#后面这个{}就是kwargs,只是因为没传值,所以为空  
      stu_register("Jack",32,"CN","Python",sex="Male",province="ShanDong") #输出 # Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'}

    四 返回值:

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

    注意

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

    五 作用域(局部全局变量):

     作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。名字的可用代码范围具体又引申为局部变量和全局变量

    局部变量|全局变量

      • 在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
      • 函数内部无法修改全局变量,但可以调用全局变量
      • 强行在局部修改全局变量
        global name 
        name = .....

      • 可以在局部修改全局列表,或字典内部元素的值
      • 全局变量作用域是整个程序,局部变量作用域是定义该变量的函数。
      • 当全局变量与局部变量同名时,在定义局部变量的函数内,局部变量起作用;在其它地方全局变量起作用。

    六 匿名函数

    匿名函数也叫lambda表达式,匿名函数的核心:一些简单的需要用函数去解决的问题,匿名函数的函数体只有一行

    特点是

    • 参数可以有多个,用逗号隔开
    • 返回值和正常的函数一样可以是任意的数据类型
    • 可以使用三元运算,一般与其他函数搭配使用
    • 节省代码量,看着高级

     与map方法搭配

    l=[1,2,3,4]
    # def func(x):
    #     return x*x
    # print(list(map(func,l)))
    
    print(list(map(lambda x:x*x,l)))

    与filter方法的搭配

    1 l=[15,24,31,14]
    # def func(x):
    #         return x>20
    # print(list(filter(func,l)))
    
    print(list(filter(lambda x:x>20,l)))

    七  函数的高级用法

    1 嵌套使用
    多层函数嵌套使用,代码定义完成之后作用域已经生成,无法更改(在外面调用内层函数时,可以调用外层函数的值)

    2高阶函数(将函数作为参数或者返回值)
    变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
    只需满足以下任意一个条件,即是高阶函数:

    • return 返回另外一个函数
    • 接受一个或多个函数作为输

    3 递归

       在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

    递归特性:

    1. 必须有一个明确的结束条件
    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
    3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

    递归的作用:

    可以用于解决很多算法问题,把复杂的问题分成一个个小问题,一一解决
    比如斐波那契数列,汉诺塔,多级评论树

    尾递归
    调用下一层时,和上一层完全无关系,只保留一层的栈数据,执行效率较高
    return cal(n+1) 尾递归
    return n*cal(n+1) n 还在等待下一层的结果,所有不是尾递归

    递归注意:

      • 默认最多递归1000层(防止占用大量内存)
      • 可以修改最大递归层次
        import os 
        sys.setreccursionlimit(1500)
  • 相关阅读:
    zoj 1239 Hanoi Tower Troubles Again!
    zoj 1221 Risk
    uva 10192 Vacation
    uva 10066 The Twin Towers
    uva 531 Compromise
    uva 103 Stacking Boxes
    稳定婚姻模型
    Ants UVA
    Golden Tiger Claw UVA
    关于upper、lower bound 的探讨
  • 原文地址:https://www.cnblogs.com/leiyiming/p/8999979.html
Copyright © 2011-2022 走看看