zoukankan      html  css  js  c++  java
  • Python全栈开发-Day3-Python基础3

    本节内容

      1. 函数基本语法及特性

      2. 参数与局部变量

      3.递归

      4.函数式编程介绍

      5.高阶函数

    1.函数基本语法及特性

     三种编程范式:

       1、面向过程:过程——> def

       2、面向对象:类——> class

       3、函数式编程:函数——> def

     

    函数是什么?

    函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,编程中的函数在英文中也有很多不同的叫法。在C中只有function,在Java里面叫做method。

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

    使用函数的好处:

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

    语法定义

    1
    2
    3
    4
    5
    def test(x):#函数定义方法、函数名、变量
      '''The function difinition!''' #对该函数的描述  
      x+=1 #函数体
      return x  #返回值
    test(1) #调用函数

    函数:

      def func1():

        '''testing1'''

        print('in the func1')

        return 0

    过程: 

      def func2():

        '''testing2'''

        print('in the func2')

    由上得出,过程就是没有返回值的函数。

    可以带参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #下面这段代码
    a,b = 5,8
    = a**b
    print(c)
     
     
    #改成用函数写
    def calc(x,y):
        res = x**y
        return res #返回函数执行结果
     
    = calc(a,b) #结果赋值给c变量
    print(c)

    return的作用

      1、终止函数的运行,即return后面的代码都将不会被执行

      2、return给调用该函数的位置,返回一个值。如,x=test1(),x就会接收到return的返回值

      3、后续程序有时需要根据之前函数return返回值的不同,进行不同的判断和运算。

    return的返回值

      return 1, 'hello', ['alex','wupeiqi'], {‘name’:'alex'}

      所以,return的个数没规定,类型没规定。把return后面的内容放入元组中全部返回,本质上return还是返回了一个值。如果之前有一个函数def test():, 用return test  时,返回值是test函数的内存地址。

    2.函数参数与局部变量

    调用方法:

      1、test()执行,()表示调用函数test,()可以有参数也可以没有

    参数

      1、形参和实参

      形参:形式参数,不是实际存在的,是虚拟变量,在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数、类型应与形参一一对应)

      实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参

      区别:形参是虚拟的,不占用内存空间,形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传送给形参,不能形参传给实参。

      2、关键字调用,与形参顺序无关;位置调用与形参一一对应。

        【注意】:关键字参数不能写在位置参数之前

      3、默认参数

        def test(x,y=2):

          print(x,y)

        test(1)

        上述代码在定义函数时对形参赋值的过程叫做设置默认参数,被赋的值叫做对应形参的默认参数。

        默认参数特点:调用函数时,默认参数非必须传递

      4、参数组:

        1)def test(*args):

           print(args)

          test(1,2,3,4,5)  #或者等价于后面这种赋值方式: test(*[1,2,3,4,5])

          输出:(1,2,3,4,5)

          这时候会把5个位置实参全部传给形参args,并且以元组的形式保存下来。定义位置调用参数组时,以*开头即可,args的名字可以是任意的。但编写规范就是*args。

        2)def test2(**kwargs):

            print(kwargs)

          test2(name='gavin',age=25,sex='M') #或者等价于后面这种赋值方式: test2(**{‘name’:'gavin','age':25,'sex':'M'})

          输出:{‘name’:'gavin','age':25,'sex':'M'}

          这时候会把3个关键字调用的实参全部传递给形参kwargs,并且以字典的方式保存,关键字为key,给关键字赋的值为value。定义关键字调用参数组时,以**开头,kwargs的名字可以是任意的,但是编写规范就是**kwargs。

        3)小结:

          *args把N个位置参数,转换成元组的方式

          **kwargs把N个关键字参数,转换成字典的方式

          【注意】: 参数组一定要放在形参的最后面

               位置参数一定要写在关键字参数之前。所以对应的,形参部分先写*args,再写**kwargs。

          

     局部变量 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    name = "Alex Li"
     
    def change_name(name):
        print("before change:",name)
        name = "金角大王,一个有Tesla的男人"
        print("after change", name)
     
    change_name(name)
     
    print("在外面看看name改了么?",name)

    输出

    1
    2
    3
    before change: Alex Li
    after change 金角大王,一个有Tesla的男人
    在外面看看name改了么? Alex Li

    全局与局部变量

    在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
    全局变量作用域是整个程序(包括所有函数的内部),局部变量作用域是定义该变量的子程序。
    当全局变量与局部变量同名时:
    在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。

    在函数内修改全局变量

      name=‘gavin

      def change_name(name):

        global name

        name='Gavin Simons'

        pass

      chang_name(name)

      在上述这种情况下,在函数内部使用global指令,声明了name为全局变量,此时在函数内部再修改name时,修改的是全局变量。同时如果在函数内部声明全局变量之前,即在文件开头并没有相同名字的全局变量,则函数内的全局变量会被新创建,在函数外部也可以进行调用。但是,虽然这样可行,但是永远不要这么干(包括在函数内修改全局变量和在函数内创建全局变量),因为这么做很难去调试,不知道是那个函数创建或修改了全局变量。

    局部变量和全局变量的特殊情况

       names=['Gavin','Simons','Jack','Rain']

      def chang_name():

        names[0] = ‘詹姆斯西蒙斯’

        print('inside func',names)

      change_name()

      print(names)

       输出:inside func ['詹姆斯西蒙斯','Simons','Jack','Rain']

         ['詹姆斯西蒙斯','Simons','Jack','Rain']

      所以只有像简单的数据类型(比如,字符串和整数)是不能在函数中修改的。但是复杂的数据类型(比如,列表、字典、集合、类,元组在什么时候都不能改)这些都是在局部里面可以直接改全局的。因为存放方式和简单数据类型不同,后者存放的是地址,而不是具体的值。

        

    3. 递归

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def calc(n):
        print(n)
        if int(n/2==0:
            return n
        return calc(int(n/2))
     
    calc(10)
     
    输出:
    10
    5
    2
    1

    递归特性:

    1. 必须有一个明确的结束条件

    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少

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

    堆栈扫盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html 

    递归函数实际应用案例,二分查找

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    data = [1367912141617182021222330323335]
     
     
    def binary_search(dataset,find_num):
        print(dataset)
     
        if len(dataset) >1:
            mid = int(len(dataset)/2)
            if dataset[mid] == find_num:  #find it
                print("找到数字",dataset[mid])
            elif dataset[mid] > find_num :# 找的数在mid左面
                print("33[31;1m找的数在mid[%s]左面33[0m" % dataset[mid])
                return binary_search(dataset[0:mid], find_num)
            else:# 找的数在mid右面
                print("33[32;1m找的数在mid[%s]右面33[0m" % dataset[mid])
                return binary_search(dataset[mid+1:],find_num)
        else:
            if dataset[0== find_num:  #find it
                print("找到数字啦",dataset[0])
            else:
                print("没的分了,要找的数字[%s]不在列表里" % find_num)
     
     
    binary_search(data,66)

      

    4.函数式编程介绍  

     

    函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。

    函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine),而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)函数计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都是不变的。

    Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

    一、定义

    简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。

    主要思想是把运算过程尽量写成一系列嵌套的函数调用。举例来说,现在有这样一个数学表达式:

      (1 + 2) * 3 - 4

    传统的过程式编程,可能这样写:

      var a = 1 + 2;

      var b = a * 3;

      var c = b - 4;

    函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:

      var result = subtract(multiply(add(1,2), 3), 4);

    因此,函数式编程的代码更容易理解。

    要想学好函数式编程,不要玩py,玩Erlang,Haskell。

        

    5.高阶函数

    变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

    即把函数本身当作一个参数,传给另一个函数。

    1
    2
    3
    4
    5
    6
    def add(x,y,f): #f为一个函数形参
        return f(x) + f(y)
     
     
    res = add(3,-6,abs)#abs是函数实参,其实就是函数abs的内存地址
    print(res)
  • 相关阅读:
    个人冲刺二(7)
    个人冲刺二(6)
    个人冲刺二(5)
    个人冲刺二(4)
    对称二叉树 · symmetric binary tree
    108 Convert Sorted Array to Binary Search Tree数组变成高度平衡的二叉树
    530.Minimum Absolute Difference in BST 二叉搜索树中的最小差的绝对值
    pp 集成工程师 mism师兄问一问
    17. Merge Two Binary Trees 融合二叉树
    270. Closest Binary Search Tree Value 二叉搜索树中,距离目标值最近的节点
  • 原文地址:https://www.cnblogs.com/GavinSimons/p/7736941.html
Copyright © 2011-2022 走看看