• 【Python】Python函数、匿名函数、变量作用域、内嵌函数和闭包、递归


    Python 函数

      函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数能提高应用的模块性,和代码的重复利用率。Python提供了许多内建函数,比如print()。也可以自己创建函数,这被叫做用户自定义函数。

    定义一个函数

    • 函数代码块以 def 关键词开头,后接函数标识符名称圆括号()
    • 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
    • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
    • 函数内容以冒号起始,并且缩进
    • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

    语法:

    def functionname( parameters ):
       "函数_文档字符串"
       function_suite
       return [expression]

    实例:

    # 创建函数
    >>> def MyFirstFunction():
        print('这是我创建的第一个函数!')
        print('谭宝宝!')
    # 调用函数
    >>> MyFirstFunction()
    这是我创建的第一个函数!
    谭宝宝!

    函数的参数:

      在 python 中,类型属于对象,变量是没有类型的:

    a=[1,2,3]
    a="Runoob"

    PS:以上代码中,[1,2,3] 是 List 类型,"Runoob" 是 String 类型,而变量 a 是没有类型,她仅仅是一个对象的引用(一个指针),可以是 List 类型对象,也可以指向 String 类型对象。

    # 如果设置了函数参数,在调用时需要填写上参数值,不然会报错
    >>> def MySecondFunction(name):
        print(name + 'I Love You')
    
        
    >>> MySecondFunction()
    Traceback (most recent call last):
      File "<pyshell#10>", line 1, in <module>
        MySecondFunction()
    TypeError: MySecondFunction() missing 1 required positional argument: 'name'
    >>> MySecondFunction('tanbaobao')
    tanbaobaoI Love You

      # 定义add函数

      >>> def add(num1,num2):
      result = num1 + num2
      print(result)

    
    


      >>> add(2,3)
      5

    形参(parameter)和实参(argument):

    >>> def MySecondFunction(name):
        '函数定义过程中的name叫形参'
    # 因为他只是个形式,表示占据一个参数的位置
    print('传递进来的' + name + '叫实参,因为他是具体的参数值') >>> MySecondFunction('tanbaobao') '传递进来的tanbaobao是实参,因为他是具体的参数值'

    关键字参数: 

      关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

      如果没有加上关键字,则会按输入的内容进行索引,加上则按照关键字索引,会按参数上的顺序输出:

    默认参数:

      默认参数即定义了默认值的参数。调用函数时,默认参数的值如果没有传入,则被认为是默认值。

    不定长参数(收集参数,可变参数):

      需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。加了星号(*)的变量名会存放所有未命名的变量参数

    def functionname([formal_args,] *var_args_tuple ):
       "函数_文档字符串"
       function_suite
       return [expression]

    PS:如果既有不定长参数,又有其他参数,建议将其他参数定义为默认参数,这样能减少出错。

    # 定义可变参数,还有其他的参数
    >>> def test(*params,other):
        print('参数长度:',len(params))
        print('第二个参数:',params[1])
    
    # 调用的时候如果忘记设置其他参数的值会报错
    >>> test(1,'谭酱',3.14,5,6,7,8)
    Traceback (most recent call last):
      File "<pyshell#58>", line 1, in <module>
        test(1,'谭酱',3.14,5,6,7,8)
    TypeError: test() missing 1 required keyword-only argument: 'other'
    # 最好的建议是将其他参数设置为默认参数,这样就算忘记传参数,也不会报错
    >>> def test(*params,other=2):
        print('参数长度:',len(params),other)
        print('第二个参数:',params[1])
    
        
    >>> test(1,'谭酱',3.14,5,6,7,8)
    参数长度: 7 2
    第二个参数: 谭酱

    补充:函数与过程

      有返回值的叫函数,没返回值的叫过程。Python只有函数,没有过程。当Python没有返回值时会返回None对象,有返回值则返回返回值。如下:

    >>> def hello():
        print('Hello tanbaobao')
    
        
    >>> temp = hello()
    Hello tanbaobao
    >>> temp
    >>> 
    >>> print(temp)
    None
    >>> type(temp)
    <class 'NoneType'>

    匿名函数

    python 使用 lambda 来创建匿名函数。

    所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。

    • lambda 只是一个表达式,函数体比 def 简单很多。
    • lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
    • lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
    • 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

    变量作用域

    全局变量和局部变量

      定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。

    注意:可以在函数内部访问全局变量,但是不要再函数内部修改全局变量的值。

    # 下面全局变量的old_price和局部变量的old_price并不是同一个变量
    # 在函数内试图修改全局变量的值,Pyhon会自动创建一个新的局部变量,名字和全局变量一致
    def discounts(price,rate):
        # 局部变量(在函数里定义的变量为局部变量,局部变量存放在其他空间)
        final_price = price * rate
        old_price = 88 # 这里后面会修改全局变量
        print('打印全局变量修改后old_price的值是:',old_price)
        return final_price
    
    # 函数外的变量为全局变量(全局变量存放在栈空间)
    old_price = float(input('请输入原价:'))
    rate = float(input('请输入折扣率:'))
    new_price = discounts(old_price,rate)
    print('修改后old_price的值是:',old_price)
    print('打折后价格是:',new_price)

    Python内嵌函数(内置)和闭包

    global关键字:可以修改全局变量

    >>> count = 5
    >>> def MyFun():
        count = 10
        print(10)
    
        
    >>> MyFun()
    10
    >>> print(count)
    5
    >>> def MyFun():
        global count
        count = 10
        print(10)
    
        
    >>> MyFun()
    10
    >>> print(count)
    10

    内嵌函数

    # 内嵌函数fun2()只能包括在fun1()函数内部
    >>> def fun1():
          print('fun1()正在被调用...')
          def fun2():
              print('fun2()正在被调用...')
          fun2()        
    
        
    >>> fun1()
    fun1()正在被调用...
    fun2()正在被调用...

    闭包

    内置函数filter()过滤器、map()映射:

    1)filter()过滤器  

      filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。不执行运算,只执行过滤判断,用于过滤迭代的对象。

    2)map()映射

      执行运算。

    递归

    实例1:f(5)=5*4*3*2*1=120

    # 实现递归求阶乘(普通方法)
    def factorial(n):
        result = n
        for i in range(1, n):
            result *= i
            print('result的结果为:', result)
    
        return result
    number = int(input('请输入一个正整数:'))
    result = factorial(number)
    print("%d 的阶乘是:%d" % (number,result)) # %d表示格式化整数

    # 使用递归求阶乘(需调用函数自身,且要有一个正确返回条件)
    def factorial(n):
        if n == 1:
            return 1
        else:
            return n * factorial(n-1)
    
    number = int(input('请输入一个正整数:'))
    result = factorial(number)
    print('%d 的阶乘是:%d' % (number,result))

    实例2:实现菲波那嵌数列

    0 1 1 2 3 5 8 13 21 34 55 (后一个数字是前两数字的和)

    实现思路:fibo(8)=fibo(7)+fibo(6)

    # 实现斐波那契数列
    def feibo(num):
        if num <= 1: # 结束条件
            return num 
        return feibo(num-1) + feibo(num-2)  # 调用自己
    
    iNum = int(input('请输入一个正整数:'))
    res = feibo(iNum)
    print('第%d 位数的斐波那契数列为:%d' % (iNum,res))

    算兔子:一对兔子,三个月生一对兔子,以此类推,20个月后能产生多少对小兔子。

    三月份的兔子 = 2月份 + 1月份的兔子

    四月份的兔子 = 3月份 + 2月份的兔子

    ......

    20月份的兔子 = 19月份 + 18月份的兔子

    # 普通方法
    def fab(n):
        n1 = 1
        n2 = 1
        n3 = 1
    
        if n < 1:
            print('输入有误!')
            return -1
    
        while (n - 2) > 0:
            n3 = n2 + n1
            n1 = n2
            n2 = n3
            n -= 1
    
        return n3
    
    result = fab(20)
    if result != 1:
        print('总共有%d对小兔子诞生!' % result)
            
    # 递归方法
    # 一对兔子,每三个月生一对,20个月后能产生多少 兔子
    def fab(n):
        if n < 1: # 判断月份不能未负数,如果为负数则输入错误,返回-1,
            print('输入有误!')
            return -1
    
        if n == 1 or n == 2: # 判断月份为1,2月份时默认为1对小兔子
            return 1
        else:
            return fab(n -1) + fab(n -2) # 调用自身函数,fab(n)为月份前两个月之和
    
    result = fab(20) # 定义计算的月份
    if result != -1: # 判断输入的月份不为负数时显示兔子20个月诞生的对数
        print('总共有%d对小兔子诞生了!' % result)

    汉诺塔游戏

      有x ,y , z三个柱子,x上有n个盘子,每次只能从x上移动一个盘子,且必须保证大盘子在小盘子下面

    # 汉诺塔游戏
    def hanoi(n, x, y, z):
        if n == 1: # 如果只有一个盘,直接从x柱 move y柱
           print(x, '-->', z)
        else:
            hanoi(n-1,x, z, y) # 1.将前n-1个盘子从x柱 move y柱上
            print(x, '-->', z) # 将最底下的最后一个盘子从x柱 move z柱上
            hanoi(n-1,y, x, z) # 2.将y柱上的n-1个盘子 move z柱上
    
    iNum = int(input('请输入汉诺塔的层数:'))
    hanoi(iNum, 'x', 'y', 'z')

     

  • 相关阅读:
    Bash快捷键
    Java Web学习笔记--JSP for循环
    Python学习笔记--简介
    Java学习笔记-数组
    JavaScript学习笔记一
    Java数组
    MongoDB学习---安装配置
    Java Web学习笔记-Servlet不是线程安全的
    Java Web学习笔记-重定向Redirect
    获取汇率的BAPI
  • 原文地址:https://www.cnblogs.com/HeiDi-BoKe/p/12102931.html
Copyright © 2020-2023  润新知