您的位置:新葡亰496net > 奥门新萄京娱乐场 > 内置函数,高阶函数

内置函数,高阶函数

发布时间:2019-11-09 07:48编辑:奥门新萄京娱乐场浏览(198)

    一、函数作用:

    一. 背景提要

    现在老板让你写一个监控程序,监控服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏空了所有的知识量,写出了以下代码

    while True:
        if cpu利用率 > 90%:
            #发送邮件提醒
            连接邮箱服务器
            发送邮件
            关闭连接
    
        if 硬盘使用空间 > 90%:
            #发送邮件提醒
            连接邮箱服务器
            发送邮件
            关闭连接
    
        if 内存占用 > 80%:
            #发送邮件提醒
            连接邮箱服务器
            发送邮件
            关闭连接
    

    上面的代码实现了功能,但即使是邻居老王也看出了端倪,老王亲切的摸了下你家儿子的脸蛋,说,你这个重复代码太多了,每次报警都要重写一段发邮件的代码,太low了,这样干存在2个问题:

    1. 代码重复过多,一个劲的copy and paste不符合高端程序员的气质
    2. 如果日后需要修改发邮件的这段代码,比如加入群发功能,那你就需要在所有用到这段代码的地方都修改一遍

    你觉得老王说的对,你也不想写重复代码,但又不知道怎么搞,老王好像看出了你的心思,此时他抱起你儿子,笑着说,其实很简单,只需要把重复的代码提取出来,放在一个公共的地方,起个名字,以后谁想用这段代码,就通过这个名字调用就行了,如下:

    def 发送邮件(内容)
        #发送邮件提醒
        连接邮箱服务器
        发送邮件
        关闭连接
    
    while True:
    
        if cpu利用率 > 90%:
            发送邮件('CPU报警')
    
        if 硬盘使用空间 > 90%:
            发送邮件('硬盘报警')
    
        if 内存占用 > 80%:
            发送邮件('内存报警')
    

    你看着老王写的代码,气势恢宏、磅礴大气,代码里透露着一股内敛的傲气,心想,老王这个人真是不一般,突然对他的背景更感兴趣了,问老王,这些花式玩法你都是怎么知道的? 老王亲了一口你儿子,捋了捋不存在的胡子,淡淡的讲,“老夫,年少时,师从京西沙河淫魔银角大王 ”, 你一听“银角大王”这几个字,不由的娇躯一震,心想,真nb,怪不得代码写的这么6, 这“银角大王”当年在江湖上可是数得着的响当当的名字,只可惜后期纵欲过度,卒于公元2016年, 真是可惜了,只留下其哥哥孤守当年兄弟俩一起打下来的江山。 此时你看着的老王离开的身影,感觉你儿子跟他越来越像了。。。

    总结使用函数的好处:

    1.代码重用

    2.保持一致性,易维护

    3.可扩展性

    1. 函数

      函数是组织好的,可重复使用的,用来实现单一,或相关功能的代码块。

      函数分为 Python 程序内置函数,用户自定义的函数。将代码定义为函数,有如下好处:

    • 代码重用
    • 保持代码一致性,易维护
    • 可拓展

    上一篇已经介绍到了高阶函数map,本节继续讲解其余的几个高阶函数

    本文笔记由Python入门和Python进阶两门课程整理而来

      函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可

    二. 什么是函数?

    函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的。

    初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域

    例如  y=2*x

    1.1 定义和调用函数

      使用 def 关键字定义一个函数,后面紧跟函数名,小括号也必不可少,语法如下:

    def func():    函数体
    

      函数在执行时,首先将函数体加载到解释器中,但是不会运行,只有当调用函数后才会执行,函数名 小括号即可调用函数:

    def func():    函数体func()      # 调用函数  
    

    map()函数

    参数:接收一个函数 f 和一个 list列表,并通过把函数 f 依次作用在 list 的每个元素上

    返回值:得到新的 list 返回 (map函数不改变原有的列表,而返回新的列表)

    示例:

    >>> ks1 = [1,2,3,4,5,6,7,8,9]
    >>> ku = map(lambda x: x 1, ks1)
    >>> type(ku)
    map
    >>> list(ku)
    [2, 3, 4, 5, 6, 7, 8, 9, 10]
    

    列表 List

    1. list1 = ['physics', 'chemistry', 1997, 2000];
    2. 倒序访问 [-1]下标访问倒数第一个元素 [0]下标访问正数第一个元素
    3. 切片同样适用于元组

      >>> L[0:3]
      #L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素。
      ['physics', 'chemistry', 1997]
      #如果第一个索引是0,还可以省略:>>> L[:3]
      #也可以从索引1开始,取出2个元素出来:>>> L[1:3]
      #只用一个 '': ''表示从头取到尾:>>> L[:]
      #切片操作还可以指定第三个参数,表示每N个取一个:>>> L[::2]
      
    4. 倒序切片

      >>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
      >>> L[-2:] //[-2~末尾]
      ['Bart', 'Paul']
      >>> L[:-2]//[0~-2)
      ['Adam', 'Lisa']
      >>> L[-3:-1]//[-3~-1)
      ['Lisa', 'Bart']
      >>> L[-4:-1:2]
      ['Adam', 'Bart']
      
    5. 列表生成式

      >>> range(1, 11)
      [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]#生成一个包含1-10的列表
      >>> [x * x for x in range(1, 11)]
      [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]#生成[1x1, 2x2, 3x3, ..., 10x10]
      #range(1, 100, 2) 可以生成list [1, 3, 5, 7, 9,...]
      
    6. 列表生成式 if判断

      >>> [x * x for x in range(1, 11) if x % 2 == 0]
      [4, 16, 36, 64, 100]
      
    7. 多层表达式

      >>> [m   n for m in 'ABC' for n in '123']
      ['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
      

      函数式编程最重要的是增强代码的重用性和可读性

    2.1 python函数

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

    函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

    python中函数定义:函数是逻辑结构化和过程化的一种编程方法。   可以理解为: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可;

    特性:

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

    1.2 返回值

      有时我们需要函数返回一些数据来报告执行的结果,所有就需要有返回值,只需要在函数中添加 return 关键字,后面跟着返回值即可。

    def func():    return 1
    

      return 将返回值传递给函数本身,我们只要调用函数,再将函数赋值给变量即可获得返回值:

    def func():    return 1res = func()        # 获得返回值,并赋值给变量 resprint1
    

      返回值可以是 0 个,也可以是 1 个 或多个:

    • 没有返回值,返回 None
    • 一个返回值,返回 返回值
    • 多个返回值,返回一个元组
    def func():    # return    # return 1    return 1, 2res = func()printNone1
    

    reduce()函数

    注意:Python3中,reduce不再是内置了,需要导入from functools import reduce

    参数:一个函数 f,一个list

    返回值:reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。

    >>> ks2 = [2,4,6,8]
    >>> ku2 = reduce(lambda x,y: x y, ks2)
    >>> type(ku2)
    int
    >>> ku2
    20
    

    元组 Tuple

    1. t = ('Adam', 1, 'Bart')
    2. 元组定义后无法修改,tuple没有 append()方法,也没有insert()和pop()方法。
    3. 空tuple >>> t = ()
    4. 创建单元素数值tuple >>> t = (1,)
    5. 索引迭代

      for index, name in enumerate(L):
      print index, '-', name
      #由 enumerate() 函数自动把每个元素变成 (index, element) 这样的tuple,再迭代,就同时获得了索引和元素本身
      

    二、函数的定义和使用

    2.2 定义一个函数

    你可以定义一个由自己想要功能的函数,以下是简单的规则:

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

    语法定义:

    def sayhi():                 # def:定义函数的关键字,函数名:sayhi,()内可以指定形参
      """The function definitions"""     # 文档描述(非必要,但是强烈建议为你的函数添加描述信息)
        print("Hello, I'm nobody!")       # 泛指代码块或程序处理逻辑
    sayhi()                   # 调用函数,通过函数名()的形式
    

    1.3 函数参数

      函数的参数可以用函数实现个性化,大致分为两类:

    • 形参:函数在定义时定义的参数
    • 实参:函数在调用时传入的参数

      形参只有在调用时才分配内存单元,调用结束,就释放。仅在函数内部有效,不能在函数外部使用。

      实参可以是常量、变量、表达式、函数,占用内存空间。

    filter()函数

    filter()函数是 Python 内置的很有用的高阶函数,简称高阶过滤函数。

    参数:filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False。filter()根据判断结果自动过滤掉不符合条件的元素。

    返回值:返回由符合条件元素组成的新list。

    >>> ks3 = [22,3,12,3,1,44,0,2,4,6,28,55,34]
    >>> ku3 = filter(lambda x: x>5, ks3)
    >>> type(ku3)
    filter
    >>> list(ku3)
    [22, 12, 44, 6, 28, 55, 34]
    

    用事实说话,Python3内置高阶函数

    完整的Python3教程--传送门

    字符串 string

      定义:

    2.3 函数和过程

    过程定义:过程就是简单特殊没有返回值的函数

    这么看来我们在讨论为何使用函数的的时候引入的函数,都没有返回值,没有返回值就是过程,没错,但是在python中有比较神奇的事情:

    def test01():
        msg = 'hello The little green frog'
        print
        msg
    
    def test02():
        msg = 'hello WuDaLang'
        print
        msg
        return msg
    
    t1 = test01()
    t2 = test02()
    
    print('from test01 return is [%s]' % t1)
    print('from test02 return is [%s]' % t2)
    

    总结: 当一个函数/过程没有使用return显示的定义返回值时,python解释器会隐式的返回None,

    所以在python中即便是过程也可以算作函数。

    def test01():
        pass
    
    def test02():
        return 0
    
    def test03():
        return 0, 10, 'hello', ['alex', 'lb'], {'WuDaLang': 'lb'}
    
    t1 = test01()
    t2 = test02()
    t3 = test03()
    
    print('from test01 return is [%s]: ' % type(t1), t1)
    print('from test02 return is [%s]: ' % type(t2), t2)
    print('from test03 return is [%s]: ' % type(t3), t3)
    

    总结:

       返回值数=0:返回None

       返回值数=1:返回object

       返回值数>1:返回tuple

    1.3.1 默认参数

      形参又分为:默认参数、位置参数、关键字参数以及可变长参数,而默认参数即在函数定义时默认赋予某个形参一个值。若函数调用时,不传入实参,函数使用默认值,否则使用实参。

    def func:      # x 默认为 2    return x   2res = func()        # 即使不传入实参函数也能正常运行print
    

    字典 dict

    1. 定义

      d = {
      'Adam': 95,
      'Lisa': 85,
      'Bart': 59,
      'Paul': 75
      }
      
    2. 打印出的字典并不按给出顺序排列 原因是 字典对于元素的存储是通过hash算法 因此 dict是无序的

    3. 查询字典d['Adam']dict[key]
    4. 使用 in 操作符查询key是否存在

      if 'Paul' in d:
      print d['Paul']
      
    5. 使用dict本身提供的一个 get 方法,在Key不存在的时候,返回None:

      >>> print d.get('Bart')
      59
      >>> print d.get('Paul')
      None
      
    6. key的元素类型可以是字符串 整数 浮点数 元组 , 而 value 的类型不限

    7. dict的特点:查找速度快,但所用空间大,牺牲空间换取速度
    8. 删除字典dict.clear();
    9. 新葡亰496net,清空字典dict.clear();
    10. 迭代字典的Key

      d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59, 'Paul': 74 }
      sum = 0.0
      for v in d.itervalues():
      sum = sum   v
      print sum / len(d)
      
    11. 迭代字典的key和value

      >>> d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
      >>> print d.items()
      [('Lisa', 85), ('Adam', 95), ('Bart', 59)]
      >>> for key, value in d.items():
      ...     print key, ':', value
      ... 
      Lisa : 85
      Adam : 95
      Bart : 59
      
    1 def 函数名(参数):
    2     函数体
    3     .....
    4     返回值
    

    2.4 函数实例:

    实例1:

    以下为一个简单的Python函数,它将一个字符串作为传入参数,再打印到标准显示设备上。

    def printme( str ):
       "打印传入的字符串到标准显示设备上"
       print str
       return
    
    # 调用函数
    printme("我要调用用户自定义函数!");
    

    实例2:

    传递参数且有返回值的函数

    a,b = 5,8
    c = a**b
    print(c)
    
    #改成用函数写
    def calc(x,y):
        res = x**y
        return res #返回函数执行结果
    
    c = calc(a,b) #结果赋值给c变量
    print(c)
    

    注: 函数定义阶段只检测函数体的语法,并不会执行

    1.3.2 位置参数和关键字参数

      普通的参数即为位置参数,在调用时实参必须与形参一一对应。而关键字参数,可以不用考虑位置的关系,只需要名字相同即可。

    def func(name, words):    print(name: words)func('Hello', words='world')    # 第一个为位置参数,第二个为关键字参数func(words='World', name='Hello')   # 不用考虑位置
    

    Tips:位置参数必须在关键字参数后面

    集合 set

    1. set的元素没有重复,而且集合是无序
    2. 创建 set s = set(['A', 'B', 'C'])//调用 set() 并传入一个 list
    3. 使用 in 操作符查询元素是否存在

      >>> 'Bart' in s
      True
      
    4. 使用add(x)添加元素

      >>> s = set([1, 2, 3])
      >>> s.add(4)
      >>> print s
      set([1, 2, 3, 4])
      
    5. 使用remove删除元素

      >>> s = set([1, 2, 3])
      >>> s.add(3)
      >>> print s
      set([1, 2, 3])
      

      -注- 

    2.5 函数的调用

    def foo():
        print('from foo')
    
    def bar(name):
        print('bar===>',name)
    
    foo()  #调用函数foo
    bar()  #调用函数bar
    

    按照有参和无参可以将函数调用分两种

    foo()      # 定义时无参,调用时也无需传入参数
    bar('egon') # 定义时有参,调用时也必须有参数
    

    按照函数的调用形式和出现的位置,分三种

    foo() #调用函数的语句形式
    
    def my_max(x,y):
        res=x if x >y else y
        return res
    res=my_max(1,2)*10000000 #调用函数的表达式形式
    print(res)
    
    res=my_max(my_max(10,20),30) #把函数调用当中另外一个函数的参数
    print(res)
    

    1.3.3 可变长参数

      可变长参数是一种参数组,它可以是多个参数,只需要在参数前加上星号即可。它可以增加函数可拓展性,当你不知道定义的函数需要定义几个参数时,使用它很方便。

      可变长参数分为:*args 和 **kwargs两类:

    • *agrs:将参数们收集起来,打包成一个元组,再一一传递给函数使用
    • **kwargs:将参数们收集并打包成一个字典

    *args

      *args 、**kwargs 是 Python 官方定义的参数名,也可以是其他名字,但是最好使用它,以便于辨认。

    def func:    print    print('有 %d 个参数' % len    print('第三个参数是:', args[2])func('P', 'y', 't', 'h', 'o', 'n')func('Python', 123, '爬虫')
    
    ('P', 'y', 't', 'h', 'o', 'n')有 6 个参数第三个参数是: t('Python', 123, '爬虫')有 3 个参数第三个参数是: 爬虫
    

    Tips:如果可变长参数后面还有参数,要将其定义为关键字参数,否则会被收集成可变长参数里面。建议在使用可变长参数时,可将其他参数设置为默认参数,或关键字参数,这样不易混淆。

    def func(*args, extra=16):# def func(*args, extra):    print    printfunc#func(5,6, extra=18)1618
    

      星号既可用来收集打包参数,也可以用来“解包”参数。当传入的参数时列表、元组、字典以及集合时,可变长参数将会将其整个打包成只有一个元组的参数,而在其前面添加一个星号,就可以将里面的元素一个个都解出来。

    def func:    printl = [1, 2, 3]t = d = {'name':'rose', 'age': 18}funcfuncfuncfuncfuncfunc
    
    ([1, 2, 3],),)({'name': 'rose', 'age': 18},)('name', 'age')
    

    **kwargs

      另一种可变长参数就是 **kwargs,它将传入的实参打包成一个字典,同样地也支持 “解包”。

    def func(x, **kwargs):    print    print    print('总共有 %d 个参数' % len    print('这些参数分别为:', kwargs)func(20, name='rose', age=18)
    
    20{'name': 'rose', 'age': 18}总共有 2 个参数这些参数分别为: {'name': 'rose', 'age': 18}
    

      解包,当传入的参数是字典时:

    def func(gender, **kwargs):    print    print    print('总共有 %d 个参数' % len    print('这些参数分别为:', kwargs)t = {'name': 'rose', 'age': 18}func('female', **t)
    
    female{'name': 'rose', 'age': 18}总共有 2 个参数这些参数分别为: {'name': 'rose', 'age': 18}
    

      当既有 *args,又有 **kwargs,以及位置参数和位置参数时:

    def func(gender, country='China', *args, **kwargs):    print(gender, country)    print    printfunc('male', 'America', 20, 30, name='rose', age=19)
    
    male America{'name': 'rose', 'age': 19}
    

    if语句

    1. Python使用4个空格作为缩进,相同缩进代码作为一个代码块
    2. if 语句后接表达式,然后用:表示代码块开始

        def:定义函数的关键字

    2.6 函数的返回值

    要想获取函数的执行结果,就可以用return语句把结果返回

    注意:

    1. 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束
    2. 如果未在函数中指定return,那这个函数的返回值为None
    3. return 一个值 函数调用返回的结果就是这个值
    4. return 值1,值2,值3,... 返回结果:(值1,值2,值3,...)

    1.4 函数文档

      函数文档即用来描述函数功能的文档,可以让别人更好地理解你的函数,定义函数文档是个好的习惯。

    def func:    """    计算一个数加一    :param x:     :return:     """    x  = 1    return xres = func()
    

    for循环

    1. 使用for语句遍历元组or列表

      L = ['Adam', 'Lisa', 'Bart']
      for name in L:
      print name
      

        返回值后可以跟多个值,最终以元组方式输出

    2.7 自定义函数

    定义函数的三种形式

    • 无参数函数:如果函数的功能仅仅只是执行一些操作而已,就定义成无参函数,无参函数通常都有返回值
    • 定义有参函数:函数的功能的执行依赖于外部传入的参数,有参函数通常都有返回值
    • 空函数

     

    1.5 函数变量

    函数

    1. 定义

      def my_abs(x):
      if x >= 0:
          return x
      else:
          return -x
      
    2. 返回多个参数的函数(返回值是一个tuple)

      import math
      def move(x, y, step, angle):
      nx = x   step * math.cos(angle)
      ny = y - step * math.sin(angle)
      return nx, ny
      >>> x, y = move(100, 100, 60, math.pi / 6)
      >>> print x, y
      151.961524227 70.0
      
    3. 默认参数 默认参数只能定义在必需参数的后面

      def power(x, n=2):
      s = 1
      while n > 0:
          n = n - 1
          s = s * x
      return s
      
    4. 可变参数 名字前面有个 * 号,我们可以传入0个、1个或多个参数给可变参数:

      def average(*args):
      sum = 0.0
      if len(args) == 0:
          return sum
      for x in args:
          sum = sum   x
      return sum / len(args)
      print average()
      print average(1, 2)
      print average(1, 2, 2, 3, 4)
      

        函数的参数:形参、实参

    三. 函数参数

    形参: 变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。

    实参: 可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值。

    新葡亰496net 1

    1.5.1 函数和过程

      在 Python 中函数和过程是分开的,函数与过程(procedure)的区别:

    • 函数:有返回值
    • 过程:简单、特殊且无返回值

      严格来说 Python 没有过程,只有函数,因为即使没有返回值,也会默认返回一个 None。

    def func():    print('Hi')res = func()printHiNone
    

    函数式编程

    python支持的函数式编程
    (1)它支持的不是纯的函数式编程,因为它允许有变量;
    (2)支持高阶函数,即函数也可以作为变量传入;
    (3)支持闭包,有了闭包就能返回一个函数;
    (4)有限度地支持匿名函数。

    高阶函数
    1.变量可以指向函数,直接对变量调用与直接对函数调用效果是一样的。例如:f=abs
    ,就是把变量f指向绝对值函数abs。f(-20)就等于abs(-20)
    2.函数名其实就是一个指向函数的变量的名字。比如:abs=len,这时候abs这个名字就不指向绝对值函数,运算完了就是取list长度的一个函数。
    3.能够接收函数作为参数的函数称之为高阶函数。因为变量可以指向函数,如f=abs;函数的参数可以接受变量,如def add(x,y,f):;所以一个函数可能可以接收另一个函数作为参数,例如:在add函数内部就调用了abs函数f ,return f(x) f(y)

        形参被调用时才会分配内存空间

     

    1.5.2 函数变量的作用域

      变量的作用域即变量可见性,也就是可用范围,一般编程语言分为:全局变量(global variable)和局部变量(local variable)。

    • 全局变量:程序开始定义时定义的变量,在函数外部,无缩进,作用域为整个程序
    • 局部变量:在子程序中定义的变量,函数内部,有缩进,作用域是整个子程序

    当全局变量与局部变量同名是,在子程序中局部变量起作用,在外面全局变量起作用。

    # 首先加载整个函数,调用函数执行函数内部,打印 tom,最后打印 rosename = 'rose'   # 全局def test():    name = 'tom'    # 局部    printtest()printtomrose    
    

      1. global 关键字

      全局变量的作用域是整个程序,函数内部亦可访问。但是不要在函数内部试图修改全局变量,这是因为 Python 使用了屏蔽(shadowing)的方式去 保护全局变量。一旦在函数内部修改,则会在函数内部创建一个一模一样的局部变量。

    name = 'rose'def test():    name = 'tom'        printtest()printtomrose
    

      从上面例子可以看出,全局变量的值没有改变。但是 Python 是支持在函数内部修改全局变量的,只需要在变量前面加上一个 global 关键字即可:

    name = 'rose'def test():    global name    name = 'tom'    printtest()printtomtom
    

    总结:当全局与局部变量名字相同时,函数内部优先读取局部变量。为了更好地区分全局与局部变量,一般地全局变量名尽量使用大小,局部变量名使用小写。

      2. 内嵌函数

      函数支持嵌套,即一个函数中嵌套另外一个函数,这种函数叫内嵌函数或内部函数。

    name = 'rose'       # def fun1():         #     name = 'tom'    #     def fun2():     #         name = 'lila'       #     fun2()          #     print     #     print         #               # print         # rosetomrose
    

    Tips:内部函数只能在内部调用,外部调用会报 NameError

    (1)map()函数

    map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。map()函数不改变原有的 list

    1. 例如

      def f(x):
      return x*x
      print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])#操作函数在前,被操作的list在后
      #结果为 [1, 4, 9, 10, 25, 36, 49, 64, 81]
      

        return 执行后,后面的不在执行,且只能有一个return

    参数分类

    从大的角度去看,函数的参数分两种:形参(变量名),实参(值)

    内置函数,高阶函数。详细的区分函数的参数分为五种:

    1. 位置参数                #标准调用:实参与形参位置一一对应
    2. 关键字参数          #关键字调用:位置无需固定
    3. 默认参数
    4. 可变长参数(*args,**kwargs)
    5. 命名关键字参数

    位置参数

    def foo(x,y,z):#位置形参:必须被传值的参数
        print(x,y,z)
    
    foo(1,2,3) #位置实参数:与形参一一对应
    

    关键字参数

    def foo(x,y,z):
        print(x,y,z)
    
    foo(z=3,x=1,y=2)      #正确 实参通过key=value的形式给形参传值
    foo(1,z=3,y=2)        #正确 位置参数与关键字参数混用
    foo(x=1,2,z=3)        #错误 关键字实参必须在位置实参后面
    foo(1,x=1,y=2,z=3)    #错误 不能重复对一个形参数传值
    

    注意:

    1. 关键字实参必须在位置实参后面
    2. 不能重复对一个形参数传值

    默认参数

    def register(name,age,sex='male'): #形参:默认参数
        print(name,age,sex)
    
    register('asb',age=40)
    register('a1sb',39)
    register('a2sb',30)
    register('a3sb',29)
    

    注意:

    1. 默认参数必须跟在非默认参数后

      def register(sex='male',name,age): #在定义阶段就会报错

       print(name,age,sex) 
      
    2. 默认参数在定义阶段就已经赋值了,而且只在定义阶段赋值一次

    3. 默认参数的值通常定义成不可变类型

    非固定参数

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

    第一种: *args

    def foo(x,y,*args): #*会把溢出的按位置定义的实参都接收,以元组的形式赋值给args
        print(x,y)
        print(args)
    

    第二种: **kwargs

    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'}
    

    命名关键字参数

    def foo(name,age,*,sex='male',height):  #*后定义的参数为命名关键字参数,这类参数,必须被传值,而且必须以关键字实参的形式去传值
        print(name,age)
        print(sex)
        print(height)
    foo('egon',17,height='185')
    

    知识点1:

    def foo(name,age=10,*args,sex='male',height,**kwargs):
        print(name)
        print(age)
        print(args)
        print(sex)
        print(height)
        print(kwargs)
    
    foo('alex',1,2,3,4,5,sex='female',height='150',a=1,b=2,c=3)
    # 输出
    alex
    1       ----->age被位置参数填充
    (2, 3, 4, 5)
    female
    150
    {'a': 1, 'c': 3, 'b': 2}
    

    知识点2:

    def foo(*args):
        print(args)
    foo(*(1,2,3,4)) = foo(1,2,3,4)    # 传入元组,1,2,3,4 <=====>*(1,2,3,4) 此时,*=* args=(1,2,3,4)
    # 输出
    (1, 2, 3, 4)
    foo(*['A','B','C','D']) = foo('A','B','C','D')  # 传入列表, 此时,['A','B','C','D']相当于('A','B','C','D')
    # 输出
    ('A', 'B', 'C', 'D')
    foo(['A','B','C','D'])     #  传入列表,此时,列表作为输出的元组中的一个元素
    # 输出
    (['A', 'B', 'C', 'D'],)
    

    知识点3:

    def foo(**kwargs):
        print(kwargs)
    
    foo(**{'y': 2, 'x': 1,'a':1}) #foo(a=1,y=2,x=1)   #实参传入字典,此时,{'y': 2, 'x': 1,'a':1}相当于a=1,y=2,x=1
    

    知识点4: 接收任意个实参

    def wrapper(*args,**kwargs):
        print(args)
        print(kwargs)
    
    wrapper(1,2,3,a=1,b=2)
    

    知识点5:

    def foo(x,y,z):
        print('from foo',x,y,z)
    def wrapper(*args,**kwargs):
        # print(args)      #args=(1,)
        # print(kwargs)     #kwargs={'y':3,'z':2}
        foo(*args,**kwargs)  #foo(*(1,),**{'y':3,'z':2}) #foo(1,z=2,y=3)
    
    wrapper(1,z=2,y=3)
    # 输出
    from foo 1 3 2
    

      

    1.5.3 闭包

      闭包是函数式编程中的一个重要数据结构,Python 中认为如果在一个内部函数里,对在外部作用域的变量进行引用,那么这个内部函数就是闭包。

    def fun1:    def fun2:        return x * y    return fun2a = fun1         # a 接收的是 fun2() 的内存地址printb = a            # a 相当于调用 fun2# 上述可以简写# res = fun1# print<function fun1.<locals>.fun2 at 0x00000000026F48C8>30
    

      从上面的例子可以看出,内部函数 fun2()对外部函数 fun1()的变量 x 进行了引用,那么 fun2()即是闭包。

      nonlocal 关键字

      但需要注意的是不能在外部函数外面调用内部函数,对外部函数的局部变量只能进行访问,不能修改。

    def fun1():    name = 'rose'    def fun2():        name = 'tom'        return name    print    return fun2fun1rose        # 外部函数局部变量 name = ‘rose' 并没有被修改
    

      如果在内部函数中想修改外部函数的局部变量可以用 nonlocal 关键字,但是需要注意的是它不能修改全局变量。

    def fun1():    name = 'rose'    def fun2():        nonlocal name       # 添加 nonlocal 关键字        name = 'tom'        return name    print    return fun2fun1tom     # 外部函数局部变量 name = ‘rose' 已经被修改
    

    (2)reduce()函数

    reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。

    1. 例如

      def f(x, y):
      return x   y
      #先计算头两个元素:f(1, 3),结果为4;
      #再把结果和第3个元素计算:f(4, 5),结果为9;
      #再把结果和第4个元素计算:f(9, 7),结果为16;
      #再把结果和第5个元素计算:f(16, 9),结果为25;
      #由于没有更多的元素了,计算结束,返回结果25。
      
    2. reduce()还可以接收第3个可选参数,作为计算的初始值。
      reduce(f, [1, 3, 5, 7, 9], 100)#结果为125

        Python中所谓的过程就是没有返回值的函数

    四. 局部变量与全局变量

    实例:

    name = "ShuKe"
    def change_name(name):
        print("before change:", name)
        name = "fengfeng"
        print("after change", name)
    
    change_name(name)
    print("在外面看看name改了么?", name)
    

    输出

    before change: ShuKe
    after change fengfeng
    在外面看看name改了么? ShuKe
    

    总结:

    • 在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
    • 全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。

    当全局变量与局部变量同名时:

    • 在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。

     

    1.6 函数即变量

      Python 程序按程序执行,遇到函数,先加载到到内存,只有当调用函数时,才会运行函数体。因此一个函数可以作为 变量在另一个函数内部调用执行,前提是第一个函数需要先加载。

      首先加载 f1,再调用 f1里的函数体,最后调用 f2里的函数体:

    def f1():           #     print('from f1')    #     f2()            # def f2():           #     print('from f2')    #                 # from f1from f2
    

      另一种情况:

    def f2():    print('from f2')def f1():    print('from f1')    f2from f1from f2
    

      第三种情况,调用 f2()时,因为 函数 f2()还未加载,导致出错(NameError: name 'f2' is not defined):

    def f1():    print('from f1')f2:    print('from f2')f1()
    

    (3)filter()函数

    filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list

    1. 例如

      def is_odd(x):
      return x % 2 == 1
      filter(is_odd, [1, 4, 6, 7, 9, 12, 17])
      #输出为 [1, 7, 9, 17]
      

      参数:

     五. 前向引用之'函数即变量'

    def action():
        print 'in the action'
        logger()
    action()
    报错NameError: global name 'logger' is not defined
    
    def logger():
        print 'in the logger'
    def action():
        print 'in the action'
        logger()
    
    action()
    
    def action():
        print 'in the action'
        logger()
    def logger():
        print 'in the logger'
    
    action()
    

      

    1.7 递归函数

      在函数内部,可以调用其他函数,如果在调用过程中直接或间接调用自身,那么这个函数就是递归函数。

      递归函数特征:

    • 必须有明确的结束条件
    • 每次进入更深一次递归时,问题规模比上一次都应有所减少
    • 递归效率不高,层次过多容易导致 栈溢出

    函数调用是通过栈实现,每调用一次,栈就会增加一层栈帧,函数返回,则减少一层。由于栈的大小有限,所有递归过多,就会导致栈溢出。

    def func:    print    if int == 0:       # 结束条件        return n    res = func   # 调用自身    return resfunc10,5,2,1
    

    (4)sorted()函数

    1. 自定义比较函数:传入两个待比较的元素 x, y,如果 x 应该排在 y 的前面,返回 -1,如果 x 应该排在 y 的后面,返回 1。如果 x 和 y 相等,返回 0。

      def reversed_cmp(x, y):#倒序排序
      if x > y:
          return -1
      if x < y:
          return 1
      return 0
      >>> sorted([36, 5, 12, 9, 21], reversed_cmp)
      [36, 21, 12, 9, 5]
      
    # Python中有三种参数:普通参数、默认参数,动态参数(针对形参说)
    # 普通参数
    # 此外对参数的理解如下:
    def test(x,y,z):# 三个都是普通参数
        print(x)
        print(y)
        print(z)
    test(1,2,3)# 实参叫位置参数,赋值时 必须一一对应 不能多,也不能少
    
    test(y=1,x=2,z=3) # 关键字参数,不需要一一对应,不能多,也不能少
    
    test(1,2,z=3) # 位置参数必需放在关键字参数左侧,不能多,也不能少
    test(1,2,y=3) # 报错,已经对y赋值,在赋值报错
    
    
    # 默认参数
    def handle(x,type='mysql'):
        print(x)
        print(type)
    handle('hello') 
    handle('hello',type='sqlite')
    handle('hello','sqlite')
    
    # 动态参数(也可以叫参数组)
    def test(x,*args):
        print(x)
        print(args)
    
    #######      * 与列表有关     ** 与字典有关
    #######      *args
    def test(x,*args):
        print(x)
        print(args)
    test(1)
    # 1
    # ()
    test(1,2,3,4,5)
    # 1
    # (2, 3, 4, 5)
    test(1,{'name':'alex'})
    # 1
    # ({'name': 'alex'},)
    test(1,['x','y','z'])
    # 1
    # (['x', 'y', 'z'],)
    test(1,*['x','y','z'])
    # 1
    # ('x', 'y', 'z')
    test(1,*('x','y','z'))
    # 1
    # ('x', 'y', 'z')
    
    
    def test(x,*args):
        print(x)
        print(args)  # 获得元组 通过for遍历传递
        print(args[0])
        print(args[0][0])
    # test(1)
    # test(1,2,3,4,5)
    # test(1,{'1':1})
    test(1,['s','a','dd'])
    # test(1,*['s','a','dd'])
    
    
    
    
    #######      **args
    
    def test(x,**kwargs):
        print(x)
        print(kwargs)
    test(1,y=2,z=3)
    test(1,1,2,2,2,2,2,y=2,z=3) # 报错
    test(1,y=2,z=3,z=3)#会报错 :一个参数不能传两个值
    
    
    
    ######## 混合
    def test(x,*args,**kwargs):
        print(x)
        print(args,args[-1])
        print(kwargs,kwargs.get('y'))
    # test(1,1,2,1,1,11,1,x=1,y=2,z=3) #报错 x
    # test(1,1,2,1,1,11,1,y=2,z=3)
    
    test(1,*[1,2,3],**{'y':1})
    test(1,*[1,2,3],**{'y':1,'z':2})
    

     六. 嵌套函数和作用域

    看上面的标题的意思是,函数还能套函数?当然可以...

    name = "Alex"
    
    def change_name():
        name = "Alex2"
    
        def change_name2():
            name = "Alex3"
            print("第3层打印",name)
    
        change_name2() #调用内层函数
        print("第2层打印",name)
    
    
    change_name()
    print("最外层打印",name)
    
    #输出
    第3层打印 Alex3
    第2层打印 Alex2
    最外层打印 Alex
    

    作用域在定义函数时就已经固定住了,不会随着调用位置的改变而改变

    # 例一:
    name='alex'
    
    def foo():
        name='lhf'
        def bar():
            print(name)
        return bar
    
    func=foo()
    func()
    
    
    # 例二:
    name='alex'
    
    def foo():
        name='lhf'
        def bar():
            name='wupeiqi'
            def tt():
                print(name)
            return tt
        return bar
    
    func=foo()
    func()
    

    输出

    lhf
    wupeiqi
    

     

    1.7.1 示例

      递归问路

      使用递归函数,实现一次递归问路操作。

    import timeperson_list = ['rose', 'tom', 'lila', 'json', 'john']def ask_way(person_list):    """    问路操作    :param person_list: 被问的人    :return:    """    print('-'*60)    if len(person_list) == 0:        return '没人知道'    person = person_list.pop()    if person == 'json':        return '%s 我知道 xxx 怎么走,它在 xxx' % person    print('你好,%s,请问 xxx 在哪里?' % person)    print('%s 回答道:我也不知道,我帮你去问问 %s' % (person, person_list))    time.sleep    res = ask_way(person_list)    return resres = ask_way(person_list)print
    
    ------------------------------------------------------------你好,john,请问 xxx 在哪里?john 回答道:我也不知道,我帮你去问问 ['rose', 'tom', 'lila', 'json']------------------------------------------------------------json 我知道 xxx 怎么走,它在 xxx
    

      二分查找

    data = [1,3,6,7,9,12,14,16,17,18,20,21,22,23,30,32,33,35]def find_num(data, num):    """    使用二分查找法,查找出一个数字的位置    """    print    if len > 1:        mid = int/2)        if data[mid] == num:            print('找到数字', data[mid])        elif data[mid] > num:            print('要找的数字在 %s 右边' % data[mid])            return find_num(data[0:mid], num)        else:            print('要找的数字在 %s 左边' % data[mid])            return find_num(data[mid 1:], num)    else:        if data[0] == num:            print('找到数字', data[0])        else:            print('要找的数字不在列表中')find_num
    
    [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]要找的数字在 18 左边[20, 21, 22, 23, 30, 32, 33, 35]要找的数字在 30 左边[32, 33, 35]要找的数字在 33 左边[35]要找的数字不在列表中
    

    (5)函数作为返回值

    1. 例如

      def f():
      print 'call f()...'
      # 定义函数g:
      def g():
          print 'call g()...'
      # 返回函数g:
      return g
      >>> x = f()   # 调用f()
      call f()...
      >>> x   # 变量x是f()返回的函数:
      <function g at 0x1037bf320>
      >>> x()   # x指向函数,因此可以调用
      call g()...   # 调用x()就是执行g()函数定义的代码
      

      函数变量:

    七. 递归

    在函数内部,可以调用其他函数。如果在调用一个函数的过程中直接或间接调用自身本身

    def calc(n):
        print(n)
        if int(n/2) ==0:
            return n
        return calc(int(n/2))
    
    calc(10)
    
    输出:
    10
    5
    2
    1
    

    新葡亰496net 2新葡亰496net 3

    #_*_coding:utf-8_*_
    __author__ = 'Linhaifeng'
    import time
    
    person_list=['alex','wupeiqi','yuanhao','linhaifeng']
    def ask_way(person_list):
        print('-'*60)
        if len(person_list) == 0:
            return '没人知道'
        person=person_list.pop(0)
        if person == 'linhaifeng':
            return '%s说:我知道,老男孩就在沙河汇德商厦,下地铁就是' %person
        print('hi 美男[%s],敢问路在何方' %person)
        print('%s回答道:我不知道,但念你慧眼识猪,你等着,我帮你问问%s...' %(person,person_list))
        time.sleep(3)
        res=ask_way(person_list)
        # print('%s问的结果是: %res' %(person,res))
        return res
    
    
    
    res=ask_way(person_list)
    
    print(res)
    
    递归问路
    

    递归问路

    递归特性:

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

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

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

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

    尾递归优化:

    新葡亰496net 4新葡亰496net 5

    data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]
    
    
    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)
    
    二分查找
    

    二分查找

    递归默认的递归层次数是:1000

    import sys
    print(sys.getrecursionlimit())      # 默认递归调用层数
    sys.setrecursionlimit(100000)       # 设置递归最大的调用层数
    print(sys.getrecursionlimit())
    '''
    1000
    100000
    '''
    

     

    1.7.2 尾调用

      尾调用又称为为递归,指的是函数在最后一步调用另一个函数的过程(最后一行不一定是最后一步)。

    # bar 在 foo 内为尾调用def bar:    return ndef foo:    return bar
    
    # bar 在 foo 内不是尾调用,最后一步为 return ydef bar:    return ndef foo:    y = bar    return y
    
    # bar1、bar2 在 foo 内都是尾调用def bar1:    return ndef bar2:    return n 1def foo:    if type is str:        return bar1    elif type is int:        return bar2
    

      尾调用优化

      定义 a 函数,a 内调用 b,b 调用 c,在内存中形成一个调用记录,又称为调用帧(call frame)。用于存储调用位置和内部变量等信息,即,直至 c 返回结果给 b,c 的调用记录消失。b 返回给 a,b 的调用记录消失,a 返回结果,a 的调用记录消失,所有记录都是先进后出,形成一个调用栈(call stack)

    (6)闭包

    内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。
    闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。

    def calc_sum(lst):
        def lazy_sum():
            return sum(lst)
        return lazy_sum
    

        分为:全局变量、局部变量

    八. 匿名函数

    1. 匿名函数就是不需要显式的指定函数,程序运行结束立刻被销毁

    语法:

    lambda x:y
    x为接收值,y为返回值
    lambda表达式中不支持if...else...简单的判断
    

    一般将简单的函数用lambda表达式形式代替,如下:

    #这段代码
    def calc(n):
        return n**n
    print(calc(10))
    
    #换成匿名函数
    calc = lambda n:n**n
    print(calc(10))
    

    你也许会说,用上这个东西没感觉有毛方便呀, 。。。。呵呵,如果是这么用,确实没毛线改进,不过匿名函数主要是和其它函数搭配使用的呢,如下:

    新葡亰496net 6新葡亰496net 7

    f=lambda x,y:x y
    print(f)
    print(f(1,2))
    
    '''
    #结果
    <function <lambda> at 0x0000000000A4E0D0>
    3
    '''
    

    示例1

    1. 匿名函数与max,min,zip,sorted的使用形式如下:
      注: max,min,zip,sorted内置函数内部依次迭代传入的对象

      # 示例所使用的内容如下所示

      salaries={ 'egon':3000, 'alex':100000000, 'wupeiqi':10000, 'yuanhao':2000 }

    新葡亰496net 8新葡亰496net 9

    print(max(salaries))            # 默认以字典的key作为元素对比
    res=zip(salaries.values(),salaries.keys())      # 使用zip函数进行转换,以values作为key,以key作为values进行max求最大值
    print(res)          # 一个zip对象
    # print(list(res))
    print(max(res))     # 最大值根据key来判断,此时res的可以为salarise的values值
    
    '''
    yuanhao     # 错误值
    <zip object at 0x0000000000A45348>
    (100000000, 'alex')
    '''
    

    zip和lambda函数

    新葡亰496net 10新葡亰496net 11

    def func(k):
        return salaries[k]
    print(max(salaries))        # 默认以key进行对比,输出错误
    print(max(salaries,key=func))       # 以key进行对比,同时将key传给函数func,形如:func(key)-->salaries[k],此时salaries[k]对应的是字典中的values,再次进行max求最大值后,获取最大值
    print(max(salaries,key=lambda k:salaries[k]))
    print(min(salaries,key=lambda k:salaries[k]))
    print(sorted(salaries))     # 默认的排序结果是从小到到,默认以key对比
    print(sorted(salaries,key=lambda x:salaries[x])) # 根据values作为对比,从小到大排列,输出key
    print(sorted(salaries,key=lambda x:salaries[x],reverse=True)) # 设置reverse=True,从大到小
    
    '''
    yuanhao         # 错误值
    alex
    alex
    yuanhao
    ['alex', 'egon', 'wupeiqi', 'yuanhao']
    ['yuanhao', 'egon', 'wupeiqi', 'alex']
    ['alex', 'wupeiqi', 'egon', 'yuanhao']
    '''
    

    max|min|sorted与lambda函数

    1. 匿名函数与map,reduce,filter的使用形式如下:
    • map()函数 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。

    注:map()函数不改变原有的 list,而是返回一个新的 list。

    新葡亰496net 12新葡亰496net 13

    map()函数
    map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。
    
    例如,对于list [1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    如果希望把list的每个元素都作平方,就可以用map()函数:
    
    
    
    因此,我们只需要传入函数f(x)=x*x,就可以利用map()函数完成这个计算:
    
    def f(x):
        return x*x
    print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
    输出结果:
    
    [1, 4, 9, 10, 25, 36, 49, 64, 81]
    注意:map()函数不改变原有的 list,而是返回一个新的 list。
    
    利用map()函数,可以把一个 list 转换为另一个 list,只需要传入转换函数。
    
    由于list包含的元素可以是任何类型,因此,map() 不仅仅可以处理只包含数值的 list,事实上它可以处理包含任意类型的 list,只要传入的函数f可以处理这种数据类型。
    
    任务
    假设用户输入的英文名字不规范,没有按照首字母大写,后续字母小写的规则,请利用map()函数,把一个list(包含若干不规范的英文名字)变成一个包含规范英文名字的list:
    
    输入:['adam', 'LISA', 'barT']
    输出:['Adam', 'Lisa', 'Bart']
    
    
    def format_name(s):
        s1=s[0:1].upper() s[1:].lower();
        return s1;
    
    print map(format_name, ['adam', 'LISA', 'barT'])
    

    map函数示例

    新葡亰496net 14新葡亰496net 15

    li=['alex','egon','shuke']
    
    res=map(lambda x:x ' Love me',li)     # 它接收一个函数(lambda)和一个 list,并通过把函数 lambda(可以是任何函数对象,只要能够处理list中的数据) 依次作用在 list 的每个元素上,得到一个新的 list 并返回
    print(res)
    print(list(res))
    
    '''
    <map object at 0x0000000000B64588>
    ['alex Love me', 'egon Love me', 'shuke Love me']
    '''
    

    map与lambda

    新葡亰496net 16新葡亰496net 17

    nums=(2,4,9,10)
    res1=map(lambda x:x**2,nums)
    print(list(res1))
    
    '''
    [4, 16, 81, 100]
    '''
    

    示例2

    reduce()函数也是Python内置的一个高阶函数。

    reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。

    新葡亰496net 18新葡亰496net 19

    # python3中reduce函数需要导入
    from functools import reduce
    
    li=[1,2,3,4,5]
    print(reduce(lambda x,y:x y,li))  # 默认的初始值为列表中的第一个元素,即x=li[0],之后会遍历li列表中的每一个元素进行求和操作,从li[1]开始
    print(reduce(lambda x,y:x y,li,100))  # 此处10为第一次传入的初始值,即x = 100,之后会遍历li列表中的每一个值进行求和操作,从li[0]开始
    
    '''
    15
    115
    '''
    

    reduce和lambda

    filter()函数也是Python内置的一个高阶函数。

    filter()函数包括两个参数,分别是function和list。该函数根据function参数返回的结果是否为真来过滤list参数中的项.

    新葡亰496net 20新葡亰496net 21

    # 示例1
    li=['alex-old','wupeiqi-old','yuanhao','egon']
    res=filter(lambda x:x.endswith('old'),li)       # x.endswith('old')值为真,则储存元素,list参数中所有为假的元素都将被删除。
    print(res)
    print(list(res))
    '''
    <filter object at 0x00000000006D4908>
    ['alex-old', 'wupeiqi-old']
    '''
    #示例2
    nums=[0,1,2,3,4,5,6,7]
    res = filter(None,nums)         # 如果filter参数值为None,就使用identity()函数,list参数中所有为假的元素都将被删除。
    print(list(res))
    '''
    [1, 2, 3, 4, 5, 6, 7]
    '''
    

    fliter和lambda

     

    1.8 匿名函数

      匿名函数即不需要显示地指定函数名的函数,Python 允许使用 lambda 关键字来创建一个匿名函数,匿名函数也被称为 lambda 表达式。

    lambda x:x 2lambda x,y,z:(x 1, y 1, z 1)    # 多个参数
    

      冒号左边是原函数参数,可以有多个参数,逗号分隔即可,冒号右边为返回值。对于有些结构比较简单的函数,可以直接定义为匿名函数:

    def func:    return x 2s = funcprint
    

      上述函数可直接定义一个匿名函数:

    f = lambda x:x 2f        # 调用
    

      匿名函数常与其他函数搭配使用:

    # 将 匿名函数当做参数传入 calc 中def calc:    ret = []    for i in li:        res = func        ret.append    return retli = [2, 3, 4, 6, 8]calc(lambda x:x 1, li)[3, 4, 5, 7, 9]
    

      lambda 表达式的作用:

    • 执行一些脚本时,省略定义函数过程
    • 对于整个程序只需要执行一两次的函数,不用考虑命名问题
    • 简化代码步骤
     1 # 如果函数的内容无global关键字,
     2 #   - 有声明局部变量
     3         # NAME = ["产品经理","廖波湿"]
     4         # def qupengfei():
     5         #     NAME = "自己"
     6         #     print('我要搞', NAME)
     7         # qupengfei()
     8 #   - 无声明局部变量
     9         # NAME = ["产品经理","廖波湿"]
    10         # def qupengfei():
    11         #     NAME.append('XXOO')
    12         #     print('我要搞', NAME)
    13         # qupengfei()
    14 
    15 # 如果函数的内容有global关键字
    16 #   - 有声明局部变量
    17         # NAME = ["产品经理","廖波湿"]
    18         # def qupengfei():
    19         #     global NAME
    20         #     NAME = "自己"
    21         #     print('我要搞', NAME)
    22         # qupengfei()
    23         # 错误示例
    24         # NAME = ["产品经理","廖波湿"]
    25         # def qupengfei():
    26         #     NAME = "自己"
    27         #     global NAME
    28         #     print('我要搞', NAME)
    29         # qupengfei()
    30 #   - 无声明局部变量
    31         # NAME = ["产品经理","廖波湿"]
    32         # def qupengfei():
    33         #     global NAME
    34         #     NAME = ["阿毛"]
    35         #     NAME.append('XXOO')
    36         #     print('我要搞', NAME)
    37         # qupengfei()
    38 
    39 ######## 全局变量变量名大写
    40 ######## 局部变量变量名小写
    41 
    42 
    43 # 优先读取局部变量,能读取全局变量,无法对全局变量重新赋值 NAME=“fff”,
    44 #     但是对于可变类型,可以对内部元素进行操作
    45 # 如果函数中有global关键字,变量本质上就是全局的那个变量,可读取可赋值 NAME=“fff”
    
     1 NAME = ["产品经理","廖波湿"]
     2 
     3 def yangjian():
     4     # NAME = "史正文"
     5     global NAME # 已经声明,NAME就是全局的的那个变量
     6     print('我要搞', NAME)
     7     NAME = "小东北"  # 修改 全局的变量
     8     print('我要搞', NAME)
     9 yangjian()
    10 
    11 
    12 
    13 
    14 #### nonlocal,指定上一级变量,如果没有就继续往上直到找到为止
    15 
    16 
    17 
    18 name = "刚娘"
    19 
    20 def weihou():
    21     name = "陈卓"
    22     def weiweihou():
    23         nonlocal name   # nonlocal,指定上一级变量,如果没有就继续往上直到找到为止
    24         name = "冷静"
    25 
    26     weiweihou()
    27     print(name)
    28 
    29 print(name)
    30 weihou()
    31 print(name)
    32 刚娘
    33 冷静
    34 刚娘
    

    九. 函数式编程

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

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

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

    2. 函数式编程

      前向引用

    1. 定义

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

    待补充......

     

    2.1 编程论

      当今编程的三种方法论:

    • 面向过程:
    • 函数式编程:特征(无变量、函数即变量)
    • 面向对象:

      函数式编程,更贴近数学,是一种抽象成都很高的编程范式,不允许函数有变量。但 Python 不是严格意义上的函数式编程,因为它允许有变量。

      函数式编程特点:

    • 函数即变量(一个函数作为参数传入另一个函数)
    • 返回值是函数(可以函数本身,也可以是别的函数)

      函数即变量

    def foo:    printdef bar:    printfoo(bar('rose'))roseNone   
    

      上面例子中,bar 打印 rose,没有返回值,因此 foo(bar相当于 foo

      返回值是函数

      返回函数本身:

    def handle():    print('from handle')    return handle       # 返回函数本身内存地址h = handle()        # 使用变量 h 接收h()         # 再调用函数本身from handlefrom handle
    

      返回别的函数:

    def test():    print('from test')def test1():    print('from test1')    return test     # 返回 test 函数的内存地址n = test1()     # 接收n()      # 相当于调用 test()
    
     1 ## Python 是先编译后运行
     2 def bar():
     3     print('from bar')
     4 def foo():
     5     print('from foo')
     6     bar()
     7 
     8 foo()
     9 
    10 
    11 
    12 def foo():
    13     print('from foo')
    14     bar()
    15 
    16 def bar():
    17     print('from bar')
    18 foo()
    19 
    20 
    21 
    22 报错:不能先调用,后定义 
    23 def foo():
    24     print('from foo')
    25     bar()
    26 
    27 foo()
    28 
    29 def bar():
    30     print('from bar')
    

    十. 内置函数

    新葡亰496net 22

    1、数学运算

      abs(), round(),pow(),divmod(),max(),min(),sum()

    新葡亰496net 23新葡亰496net 24

    '''
    1、数学运算
    '''
    # abs(-5)  # 取绝对值,也就是5
    # round(2.623423, 4)  # 四舍五入取整,也就是3.0, 4为精准到四位四舍五入
    # pow(2, 3)  # 相当于2**3,如果是pow(2, 3, 5),相当于2**3 % 5
    # divmod(9, 2)  # 返回除法结果和余数
    # max([1, 5, 2, 9])  # 求最大值
    # min([9, 2, -4, 2])  # 求最小值
    # sum([2, -1, 9, 12])  # 求和
    

    数学运算

    2、工厂函数

      int(), float(), str(), bool(), slice(), list(), tuple(), dict(), set(), frozenset()

    新葡亰496net 25新葡亰496net 26

    # int("5")  # 转换为整数 integer
    # float(2)  # 转换为浮点数 float
    # str(2.3)  # 转换为字符串 string
    # bool(0)  # 转换为相应的真假值,在Python中,0相当于False在Python中,下列对象都相当于False:[], (), {}, 0, None, 0.0, ''
    # slice(5, 2, -1)  # 构建下标对象 slice,切片函数
    # list((1, 2, 3))  # 转换为表 list
    # tuple([2, 3, 4])  # 转换为定值表 tuple
    # dict(a=1, b="hello", c=[1, 2, 3])  # 构建词典 dictionary
    # set()          创建集合函数
    # frozenset()  创建一个不可修改的集合 如:s=frozenset({1,2}) # 定义不可变集合
    

    工厂函数

    3、类型转换

      ord(), chr(), bin(), hex(), oct(), complex()

    新葡亰496net 27新葡亰496net 28

    ord("A")  # "A"字符对应的数值
    chr(65)  # 数值65对应的字符
    bin(56)  # 返回一个字符串,表示56的二进制数
    hex(56)  # 返回一个字符串,表示56的十六进制数
    oct(56)  # 返回一个字符串,表示56的八进制数
    complex(3, 9)  # 返回复数 3   9j
    

    类型转换

    4、序列操作

      all(), any(), sorted(), reversed()

    新葡亰496net 29新葡亰496net 30

    all([True, 1, "hello!"])        # 是否所有的元素都相当于True值
    any(["", 0, False, [], None])   # 是否有任意一个元素相当于True值
    reversed([1,5,3])               # 返回反序的序列,也就是[3,5,1]
    

    序列操作

    5、编译执行函数

      repr(), compile(), eval(), exec()

    新葡亰496net 31新葡亰496net 32

    # repr(me)                         # 返回一个对象的字符串表示。有时可以使用这个函数来访问操作。
    # compile("print('Hello')",'test.py','exec')       # 编译字符串成为code对象
    # eval("1   1")                     # 解释字符串表达式。参数也可以是compile()返回的code对象
    '''
    # cmd='print("你瞅啥")'
    # 
    # dic="{'a':1,'b':2}"
    # d=eval(dic)
    # print(type(d),d['a'])
    # 
    # with open('user.db','w',encoding='utf-8') as f:
    #     user_dic={'name':'egon','password':'123'}
    #     f.write(str(user_dic))
    # 
    # with open('user.db','r',encoding='utf-8') as f:
    #     dic=f.read()
    #     print(dic,type(dic))
    #     dic=eval(dic)
    #     print(dic['name'])
    '''
    # exec("print('Hello')")            #  exec()执行字符串或complie方法编译过的字符串,没有返回值
    

    编译执行函数

    6、帮助函数

      dir(), help(), id(), len(), challables()

    新葡亰496net 33新葡亰496net 34

    '''
    6、帮助函数
    '''
    # dir()  不带参数时返回当前范围内的变量,方法和定义的类型列表,带参数时返回参数的属性,方法列表
    '''
    l=[]
    print(dir(l)) #查看一个对象下面的属性
    '''
    # help()  返回对象的帮助文档
    '''
    print(help(l))
    '''
    # id()  返回对象的内存地址
    '''
    # x=1
    # y=x
    # print(id(x),id(y))
    #
    # print(x is y) #判断的是身份
    '''
    # len()  返回对象长度,参数可以是序列类型(字符串,元组或列表)或映射类型(如字典)
    # challable()  判断对象是否可以被调用,能被调用的对象就是一个callables对象,比如函数和带有__call__()的实例
    '''
    def func():
        pass
    print(callable(func))
    '''
    

    帮助函数

    7、作用域查看函数

      globals(), locals(), vars()

    新葡亰496net 35新葡亰496net 36

    #globals()  返回一个描述当前全局变量的字典
    #locals()  打印当前可用的局部变量的字典
    #vars() #等于locals()
    

    作用域查看函数

    8、迭代器函数

      iter(), next(), enumerate(), range()#python3中为生成一个迭代器

    新葡亰496net 37新葡亰496net 38

    '''
    8、迭代器函数
    '''
    '''
    iter(o[, sentinel])
    返回一个iterator对象。该函数对于第一个参数的解析依赖于第二个参数。
    如果没有提供第二个参数,参数o必须是一个集合对象,支持遍历功能(__iter__()方法)或支持序列功能(__getitem__()方法),
    参数为整数,从零开始。如果不支持这两种功能,将处罚TypeError异常。
    如果提供了第二个参数,参数o必须是一个可调用对象。在这种情况下创建一个iterator对象,每次调用iterator的next()方法来无
    参数的调用o,如果返回值等于参数sentinel,触发StopIteration异常,否则将返回该值。
    '''
    # next()  返回一个可迭代数据结构(如列表)中的下一项
    # enumerate()  # 返回一个可以枚举的对象,该对象的next()方法将返回一个元组
    # x=range(10)
    # enumerate([1,2,3]).__next__()
    # range()  根据需要生成一个指定范围的数字,可以提供你需要的控制来迭代指定的次数
    

    迭代器相关函数

    9、其他函数

      hash(), filter(), format(), input(), open(), print(), zip(), map(), __import__

    新葡亰496net 39新葡亰496net 40

    # hash() 哈希值用于快递比价字典的键。
    # 1. 只要校验的内容一致,那hash得到结果永远一样
    # 2. 不可逆
    # 3. 只要采用的哈希算法一样,那无论被校验的内容有多长,hash的到的结果长度都一样
    # print(hash('asdfasdfsadf'))
    # print(hash('asdfasdfsadf'))
    
    # filter()  过滤器,构造一个序列,等价于[ item for item in iterables if function(item)],在函数中设定过滤条件,逐一循环迭代器中的元素,将返回值为True时的元素留下,形成一个filter类型数据
    '''
    filter(function, iterable)
    参数function:返回值为True或False的函数,可以为None。
    参数iterable:序列或可迭代对象。
    >>> def bigerthan5(x):
    ...     return x > 5
    >>> filter(bigerthan5, [3, 4, 5, 6, 7, 8])
    [6, 7, 8]
    '''
    
    # format()  #格式化输出字符串,format(value, format_spec)实质上是调用了value的__format__(format_spec)方法
    '''
    "I am {0}, I like {1}!".format("wang", "moon")
    "I am {}, I like {}!".format("wang", "moon")
    "I am {name}, I like {msg}!".format(name = "wang", msg ="moon")
    '''
    
    # input()  #获取用户输入内容
    # open()  打开文件
    # print()  输出函数
    
    # zip()  拉链函数将对象逐一配对
    # s='helloo'
    # l=[1,2,3,4,5]
    #
    # z=zip(s,l)
    # print(z)
    # for i in z:
    #     print(i)
    
    
    # import time
    # m=__import__('time') #以字符串的形式导入模块
    # m.sleep(3000)
    
    '''
    map(function, iterable,...)
    对于参数iterable中的每个元素都应用fuction函数,并将结果作为列表返回。
    如果有多个iterable参数,那么fuction函数必须接收多个参数,这些iterable中相同索引处的元素将并行的作为function函数的参数。
    如果一个iterable中元素的个数比其他少,那么将用None来扩展改iterable使元素个数一致。
    如果有多个iterable且function为None,map()将返回由元组组成的列表,每个元组包含所有iterable中对应索引处值。
    参数iterable必须是一个序列或任何可遍历对象,函数返回的往往是一个列表(list)。
    
    li = [1,2,3]
    data = map(lambda x :x*100,li)
    print(type(data))
    data = list(data)
    print(data)
    
    运行结果:
    
    <class 'map'>
    [100, 200, 300]
    '''
    

    其他函数

    10、面向对象使用函数

      super(), isinstance(), issubclass(), classmethod(), staticmethod(), proerty(), delatter(), hasattr(), getattr(), setattr()

    新葡亰496net 41新葡亰496net 42

    #super()  调用父类的方法
    
    # isinstance()  检查对象是否是类的对象,返回True或False
    # issubclass()  检查一个类是否是另一个类的子类。返回True或False
    
    
    # classmethod()  # 用来指定一个方法为类的方法,由类直接调用执行,只有一个cls参数,执行雷的方法时,自动将调用该方法的类赋值给cls.没有此参数指定的类的方法为实例方法
    # staticmethod
    # property
    
    # delattr()  # 删除对象的属性
    # hasattr
    '''
    hasattr(object,name)
    判断对象object是否包含名为name的特性(hasattr是通过调用getattr(object,name))是否抛出异常来实现的。
    参数object:对象
    参数name:特性名称
    >>> hasattr(list, 'append')
    True
    >>> hasattr(list, 'add')
    False
    '''
    #getattr()  获取对象的属性
    #setattr()  与getattr()相对应
    

    面向对象使用函数

    11. 内置函数实例

    新葡亰496net 43新葡亰496net 44

    字典的运算:最小值,最大值,排序
    salaries={
        'egon':3000,
        'alex':100000000,
        'wupeiqi':10000,
        'yuanhao':2000
    }
    
    迭代字典,取得是key,因而比较的是key的最大和最小值
    >>> max(salaries)
    'yuanhao'
    >>> min(salaries)
    'alex'
    
    可以取values,来比较
    >>> max(salaries.values())
    >>> min(salaries.values())
    但通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键
    >>> max(salaries,key=lambda k:salary[k])
    'alex'
    >>> min(salaries,key=lambda k:salary[k])
    'yuanhao'
    
    
    也可以通过zip的方式实现
    salaries_and_names=zip(salaries.values(),salaries.keys()) 
    
    先比较值,值相同则比较键
    >>> max(salaries_and_names)
    (100000000, 'alex')
    
    salaries_and_names是迭代器,因而只能访问一次
    >>> min(salaries_and_names)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: min() arg is an empty sequence
    
    
    sorted(iterable,key=None,reverse=False)
    

    几个内置函数实例

    内置参数详解: https://docs.python.org/3/library/functions.html?highlight=built#ascii 

     

    2.2 高阶函数

      函数式编程的两个特征:函数即变量,返回值是函数,只需满足其中一个条件,即可成为高阶函数。

    def add:    return fprint(add(-5, 6, abs))11
    

      上面例子中,内置函数 abs 作为参数传入函数 add。

      递归:

    2.2.1 map 函数

      map(function, sequence) 函数是高阶函数的一种,它有两个参数:第一个为函数,另一个接收一个序列。

      其作用是将序列中每个元素,作为函数参数传入第一个参数中,直至序列中每个元素都被循环,返回一个迭代器对象,用 list 可获得结果。

    # 对列表 l 中每个元素加 1li = [2, 3, 4, 5, 6]def add_one:    return x 1res = map(add_one, li)printprint)<map object at 0x0000000002C5C0B8>[3, 4, 5, 6, 7]
    

      上面例子中 map 函数将列表 li 的每个中每个元素取出,再传入 add_one 中。

      同样地也可以使用 lambda 表达式与 map 函数简写:

    res = map(lambda x:x 1, li)
    

      传入两个列表:

    res = map(lambda x, y: x y, [1, 3, 5], [2, 4, 6])print)
    

      新葡亰496net 45

    2.2.2 filter 函数

      filter(function or None, iterable)函数有两个参数:第一个可以是函数也可以是 None,第二个为可迭代对象。

    • 第一个参数为函数:将序列中每个元素取出作为参数,传入第一个参数中,判断,并把为 True 的值返回
    • 第一个参数为 None:将序列中为 True 的元素返回

      第一个参数为函数:

    # 过滤掉以 123 结尾的名字names = ['rose_123', 'lila_123', 'john']def filter_123:    return not x.endswith('123')        # 返回没有以 123 结尾的名字res = filter(filter_123, names)listjohn
    

      使用 lambda 表达式简写:

    res = filter(lambda x: not x.endswith('123'), names)list
    

      第一个参数为 None:

    res = filter(None, [1, 2, 0, True, False])list[1, 2, True]
    

    新葡亰496net 46新葡亰496net 47

    2.2.3 reduce 函数

      reduce(function, sequence[, initial])函数三个参数:第一个为函数,第二个为序列,第三个可选为初始值。

      Python3 把 reduce 函数集成到 functools 模块中,因此每次使用时,需要from functools import reduce。它可以把一个函数作用在一个序列上,这个函数必须接收两个参数。首先将序列中的前两个元素取出,传入函数中,返回值再与序列中接下来的元素做累积计算,直至序列中的每个元素都被循环。

      求列表中所有元素的乘积:

      常规:

    nums = [1, 2, 3, 100]def reduce_test(func, array):    res = array.pop    for i in array:        res = func    return ress = reduce_test(lambda x,y: x*y, nums)print600
    

      reduce:

    from functools import reducenums = [1, 2, 3, 100]res = reduce(lambda x,y : x*y, nums)print600
    

      首先将 nums 前两个元素,即 1、2 传入lambda x,y: x*y中,返回 x*y。再将 3 传入,最后将 100 传入,相当于*100)

    指定初始值:

    from functools import reducenums = [1, 2, 3, 100]res = reduce(lambda x,y : x*y, nums, 6)     # 相当于 *3)*100print3600
    

      累加计算:

    from functools import reducereduce(lambda x,y: x y, [1, 2, 3, 4, 5])15
    
     1 递归问路:
     2 
     3 import time
     4 
     5 person_list=['alex','wupeiqi','linhaifeng','zsc']
     6 def ask_way(person_list):
     7     print('-'*60)
     8     if len(person_list) == 0:
     9         return '根本没人知道'
    10     person=person_list.pop(0)
    11     if person == 'linhaifeng':
    12         return '%s说:我知道,老男孩就在沙河汇德商厦,下地铁就是' %person
    13 
    14     print('hi 美男[%s],敢问路在何方' % person)
    15     print('%s回答道:我不知道,但念你慧眼识猪,你等着,我帮你问问%s...' % (person, person_list))
    16     time.sleep(1)
    17     res=ask_way(person_list)
    18 
    19 
    20     print('%s问的结果是: %res' %(person,res))
    21     return res
    22 
    23 res=ask_way(person_list)
    24 print(res)
    

    2.2.4 sorted 函数

      排序算法在程序中是经常用到的算法,无论是冒泡还是快排,其核心都是比较两个元素的大小。

    • 数字:直接比较
    • 字符串/字典:需要用函数抽象出来比较

      sorted(iterable, key, reverse)函数也是一个高阶函数,在列表内置方法中我们就已经接触到了,它可以对一个列表进行排序,默认从小到大。

    sorted([1, -3, 2])[-3, 1, 2]
    

      此外,它还接收一个 key 函数来自定义排序,key 函数作用在列表中的每个元素上,再进行比较,如按绝对值排序:

    sorted([1, -3, 2], key=abs)[1, 2, -3]
    

      第三个参数 reverse,可以反向排序:

    sorted([1, -3, 2], key=abs, reverse=True)[-3, 2, 1]
    

      上面都是针对数字的排序,直接比较其大小即可。但是对于字符串来说,一般地都是比较其首字母在 ASCII 中的大小:

    sorted(['b', 'a', 'Z'])     # 因为在 ASCII中 Z<a['Z', 'a', 'b']
    

      现在我们不想按照 ASCII 来排序,而是按照字母表排序,那么我们可以通过指定 key 函数,将所有字符串转换为大写或小写即可实现:

    sorted(['b', 'a', 'Z'], key=str.upper)['a', 'b', 'Z']
    

    递归问路  

    2.2.5 偏函数

      functools 模块提供了很多功能,其中一个就是偏函数。

      当函数的参数个数太多,需要简化时,使用 functools.partial 创建一个偏函数,这个新的函数可以固定住原函数的部分参数,从而调用更简单。

    语法结构:

    from functools import partialfunc2 = partial(func, *args, **kwargs)  # 第一个参数:要固定的函数,第二个:原函数的位置参数,第三个:关键字参数
    

      第一个参数可以是自定义的函数,也可以是内置函数。

      int() 函数可以把字符串转换为整型,默认按照十进制转换:

    >>> int('123')123
    

      int() 函数还额外提供一个 base 参数,如果传入 base,就可以做 N 进制转换:

    >>> int('123', base=8)      # 按照八进制转换83
    

    内置函数

      假如要转换大量的二进制字符串,每次都要传入 base,就会很繁琐。我们可以利用偏函数将 base=2 固定住,定义一个新的函数,每次只需要传入要转换的字符串即可:

    >>> from functools import partial>>> int2 = partial(int, base=2)     # 将 base = 2 固定住>>> int2('100')     # 相当于 kw={'base': 2}  int('100', **kw)4
    

    自定义函数

      当我们调用某个函数,已知某个参数的值时,可以将其固定住:

    from functools import partialdef add:    return x % yadd2 = partial  # 自动将 5 作为 *args 的一部分放在最左边,也就是 5 % 100print)# 101
    

      递归特性:

    2.2.6 练习

      将列表中年龄小于等于 18 岁的人过滤出来。

    people = [    {'name': 'rose', 'age': 18},    {'name': 'lila', 'age': 30},    {'name': 'tom', 'age': 60}]res = filter(lambda p: p.get('age') <= 18, people)print)[{'name': 'rose', 'age': 18}]
    

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

    3. 内置函数

      函数分为 Python 内置函数和自定义函数,内置函数有很多,但是真正能用到的也比较少。

    # abs():求一个数字的绝对值>>> abs5# all:判断序列中所有元素是否为 True,如果序列为空,也返回 True,返回布尔值>>> all([1, 2, 0])False# any:序列中元素 bool,只要有一个为 True,则返回 True,如果序列为空,返回 False>>> anyFalse>>> any(['', 0, 1])True# bin:十进制转二进制>>> bin'0b1010'# hex:十进制转十六进制>>> hex'0xa'# bool():转换为布尔类型>>> boolFalse>>> boolFalse>>> bool('')False# bytes(obj,encoding=None):将对象编码# bytes(obj,encoding=None).decode:解码,用什么编码就应用什么解码>>> name = '你好'>>> bytes(name, encoding='utf-8')b'xe4xbdxa0xe5xa5xbd'>>> bytes(name, encoding='utf-8').decode('utf-8')'你好'# chr:返回一个数字在 ASCII 中对应的值>>> chr'Z'# ord:查询一个字符咋 ASCII 中的对应的数字>>> ord('Z')90# dict():创建一个字典>>> d = dict()>>> type<class 'dict'># dir:返回一个对象的所有方法名字>>> dir# help:查看帮助文档>>> help(list.append)Help on method_descriptor:append    L.append -> None -- append object to end    # dirmod:返回一个元组,结果为 x/有的商和余数,一般用作网页分页>>> divmod# id:查看一个对象的内存地址>>> id1750035808# globals():查看全局变量# locals():查看局部变量# pow:幂运算,z 可选, pow相当于 %z>>> pow1000>>> pow0# reversed:反转一个序列>>> list(reversed('abc'))['c', 'b', 'a']>>> list(reversed([1, 2, 3]))[3, 2, 1]# round(number,ndigits):四舍五入,保留几位有效小数>>> round4>>> round4.56# set:转换成集合、创建一个集合>>> set('123'){'2', '3', '1'}>>> s = set()>>> type<class 'set'># slice(statr,stop[,step]):序列切片/分片>>> l = 'hello'>>> s = slice>>> l[s]'l'# str():转换为字符串>>> str'123'# sum(iterable, start=0):求序列中所有元素的和,还可指定>>> l = [1, 2, 3, 4]>>> sum10>>> sum11# tuple():转换为元组>>> tuple(['a', 1])('a', 1)# vars:返回对象的属性和属性值的字典对象。>>> vars(){'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' >, 'name': '你好', 'd': "{'name:': 'rose'}", 's': slice(2, 3, None), 'p': {'name': 'rose', 'age': 18, 'gender': 'male'}, 't': <zip object at 0x0000000002D9FF08>, 'i': ('c', 3), 'age': {'rose': 18, 'tom': 19}, 'li': 'hello', 'l': [1, 2, 3, 4]} >>> vars ....  # __import__():当模块名是字符串是,可以使用。 >>> module_name = 'test'>>> __import__(module_name)<module 'test' from 'C:\Users\HJ\Anaconda3\lib\test\__init__.py'>>>> import module_nameTraceback (most recent call last):  File "<stdin>", line 1, in <module>ModuleNotFoundError: No module named 'module_name'
    

      1. eval()

      eval(expression,[globals[,locals]),用于执行一个字符串表达式,并返回表达式值,可以去掉字符串的引号

    >>> d = "{'name:': 'rose'}">>> type<class 'str'>>>> s = eval>>> type<class 'dict'>
    

      字符串中表达式的值,也可以计算:

    >>> express = '1*2 3'>>> eval5
    

      2. hash()

      hash做哈希运算,不管对象有多长,经过哈希运算后的值长度都相同,也不能根据 hash 值反推出原始对象。

      可用于校对软件/文件是否被别人篡改,还可用于判断软件或文件是否下载完整(检验官方给出的 hash 值与自己下载完毕 hash 的值是否相同)

    • 可哈希数据类型:即不可变数据类型,如:字符串、元组
    • 不可哈希数据类型:即可变数据类型,如:列表、字典、集合
    >>> hash('abc')5994226220732616244>>> hash('123')-3466646395452377901
    

      3. isinstance

      两个都是用于判断数据类型,官方建议使用 isinstance。

    >>> type<class 'int'>nums = '123'if type is str:    res = int   1
    

      isinstance(x,A_tuple)有两个参数:第一个是待确定类型的数据,第二个是指定一个数据类型,判断两者是否一致,返回一个布尔值。

    >>> isinstanceTrue
    

      4. zip()

      zip(ite1[,iter2[...]])函数接收两个序列,要求它们元素数据相等,返回两个序列元素一一对应的元组(返回的是 zip 对象的内存地址)。

    >>> p = {'name': 'rose', 'age': 18, 'gender': 'male'}>>> t = zip, p.values>>> list[('name', 'rose'), ('age', 18), ('gender', 'male')]>>> list(zip(['a', 'b', 'c'], [1, 2, 3]))[('a', 1), ('b', 2), ('c', 3)]>>> for i in zip(['a', 'b', 'c'], [1, 2, 3]):...     print...('a', 1)('b', 2)('c', 3)
    

      5. max

      max(iterable, key, default)、min()返回一个序列中的最大、小元素。

      特性:

    • 原理是将序列中每个元素都循环遍历出来比较
    • 首先比较第一个字符,分出大小则停止比较,若分出,钻继续比较。不同数据类型不能比较
    • 字典比较,默认比较 key
    >>> max([1, 2, 3])                                       3                                                        >>> max(['a', 'b'])                                      'b'                                                      >>> max(['a12', 'a2'])                 # a 相同,2>1               'a2'                                   # b>a                   >>> max(['a12', 'b10'])                                  'b10'                                                             >>> age = {'rose': 18, 'tom': 19}      # 字典比较默认比较 key                  >>> max                                             'tom'                                          >>> max(zip(age.values(), age.keys        #  既比较大小,又把名字也打印出来                                        (19, 'tom')                                              
    

      max()还可以指定比较方法:

    # 取出 age 比较>>> people = [    {'name': 'rose', 'age': 18},    {'name': 'lila', 'age': 30},    {'name': 'tom', 'age': 60}]>>> max(people, key=lambda dic:dic.get('age')){'name': 'tom', 'age': 60}
    

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

        3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,

         每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,

         所以,递归调用的次数过多,会导致栈溢出)

    新葡亰496net 48新葡亰496net 49

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

    二分法

       

      作用域:

         函数的作用域只跟函数声明时定义的作用域有关,跟函数的调用位置无任何关系  

     1 name = 'jack'
     2   
     3 def foo():
     4     name = 'jerry'
     5     def bar():
     6         name = 'lucy'
     7         print(name)
     8         def tt():
     9             print(name)
    10         return tt
    11     return bar
    12 
    13 func = foo() # 得到的是bar()函数的内存地址
    14 func()() # 执行bar() 函数
    15 # 可以直接foo()()()
    

      匿名函数:

        匿名函数就是不需要显示的指定函数名。模式:lambda x:x 1   

     1 如下代码:
     2 def calc(x):
     3     return x 1
     4 calc(10)
     5 
     6 用匿名函数表示:
     7 func = lambda x:x 1
     8 print(func(10))
     9 
    10 
    11 
    12 def test(x,y,z):
    13      return x 1,y 1  #----->(x 1,y 1)
    14 
    15 匿名函数表示:
    16 lambda x,y,z:(x 1,y 1,z 1)
    
        匿名函数主要用于和其他函数的搭配:
    
    1 l=[3,2,100,999,213,1111,31121,333]
    2 print(max(l))
    3 
    4 dic={'k1':10,'k2':100,'k3':30}
    5 
    6 
    7 print(max(dic))
    8 print(dic[max(dic,key=lambda k:dic[k])])
    
     1 res = map(lambda x:x**2,[1,5,7,4,8])
     2 for i in res:
     3     print(i)
     4 
     5 输出
     6 1
     7 25
     8 49
     9 16
    10 64
    

     

      函数式编程:

        编程方法论:面向过程、面向对象、函数式

        面向过程:简单的说就是没有返回值,一层一层的往下传递,直到实现需求

        面向对象:把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为

        举例五子棋:

          面向过程:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。

          面向对象:1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。

       什么是函数式编程:函数式=编程语言定义的函数   数学意义的函数
            通俗来讲,函数式就是利用编程语言实现数学函数,这种函数内对象是永恒不变的,要么返回值是函数,要么参数是函数,
            没有for和while循环,所有的循环都用递归实现,没有变量赋值,即不改变。但是可读性低,很精简。
            
    

    新葡亰496net 50新葡亰496net 51

     1 一、不可变:没有变量,也就没有赋值和修改
     2 # 非函数式:
     3 a=1
     4 def foo():
     5     global a # 尽量啥用
     6     a = 2
     7     return a
     8 foo()
     9 print a
    10 
    11 # 函数式
    12 a = 1
    13 def foo():
    14     return a 1
    15 foo()
    16 print a                
    17 
    18 ###高阶函数  1、函数接收的参数是一个函数名  2、返回值中包含函数
    19 ###满足之一就是高阶函数
    20 
    21 二、函数即变量,把函数当做参数传递给另一个函数
    22 def foo(n): #n=bar
    23     print(n)
    24 
    25 def bar(name):
    26     print('my name is %s' %name)
    27 
    28 foo(bar)
    29 foo(bar()) #报错
    30 foo(bar('alex'))
    31 
    32 
    33 三、返回值中包含函数
    34 def bar():
    35     print('from bar')
    36 def foo():
    37     print('from foo')
    38     return bar
    39 n=foo()
    40 n()
    41 
    42 
    43 def hanle():
    44     print('from handle')
    45     return hanle
    46 h=hanle()
    47 h()
    48 
    49 
    50 
    51 def test1():
    52     print('from test1')
    53 def test2():
    54     print('from handle')
    55     return test1()
    

    函数式编程样例分析

    新葡亰496net 52新葡亰496net 53

     1 四、尾调用:在函数的最后一步调用另一个函数(最后一行不一定是函数的最后一步)
     2 # 函数bar在foo内是尾调用
     3 def bar(n):
     4     return n 
     5 def foo(x):
     6     return bar(x)
     7 
     8 # 函数bar1和bar2在foo内是尾调用,二者在if判断条件不同的情况下都有可能作为函数的最后一步
     9 def bar1(n):
    10     return n
    11 def bar2(n):
    12     return n 1
    13 
    14 def foo(x):
    15     if type(x) is str:
    16         return bar1()
    17     else:
    18         return bar2()
    19 
    20 
    21 # 函数bar在foo内不是尾调用
    22 def bar(n):
    23     return n 
    24 def foo(x):
    25     y = bar(x)
    26     return y
    27 
    28 # 函数bar在foo内不是尾调用
    29 def bar(n):
    30     return n 
    31 def foo(x):
    32     return bar(x)  1 # 先执行bar(x)完了还要执行 1操作 所以不是最后一步
    

    函数式编程样例分析2

    新葡亰496net 54新葡亰496net 55

     1 背景:最后一步调用递归,不要不保存上一次的状态,直接进入下一次递归
     2 
     3 非尾递归
     4 def foo(seq):
     5     if len(seq) == 1:
     6         return seq[0]
     7     head,*tail=seq
     8     return head   foo(tail) #每次都用head保存状态
     9 print(foo(range(100)))
    10 
    11 尾递归
    12 def cal(l):
    13     print(l)
    14     if len(l) == 1:
    15         return l[0]
    16     first,second,*args=1
    17     1[0]=first*second
    18     l.pop(1)
    19     return cal(l)
    

    尾递归优化例子

            高阶函数:(map。filter。reduce.....)

    新葡亰496net 56新葡亰496net 57

     1 #高阶函数 1、函数接收的参数是一个函数名  2、返回值中包含函数
     2 # 满足其一即可
     3 # 把函数当作参数传给另外一个函数
     4 # def foo(n): #n=bar
     5 #     print(n)
     6 #
     7 # def bar(name):
     8 #     print('my name is %s' %name)
     9 #
    10 # foo(bar)
    11 # foo(bar())
    12 # foo(bar('alex'))
    13 
    14 #返回值中包含函数
    15 # def bar():
    16 #     print('from bar')
    17 # def foo():
    18 #     print('from foo')
    19 #     return bar
    20 # n=foo()
    21 # n()
    22 
    23 def hanle():
    24     print('from handle')
    25     return hanle
    26 h=hanle()
    27 h()
    28 
    29 def test1():
    30     print('from test1')
    31 def test2():
    32     print('from handle')
    33     return test1()
    

    View Code

            map函数: 

               map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。

    新葡亰496net 58新葡亰496net 59

     1 num_l = [1, 2, 10, 5, 3, 7]
     2 def map_test(func, array):  # func=lambda x:x 1    arrary=[1,2,10,5,3,7]
     3     ret = []
     4     for i in array:
     5         res = func(i)  # add_one(i)
     6         ret.append(res)
     7     return ret
     8 print(map_test(lambda x: x   1, num_l))
     9 
    10 res = map(lambda x: x   1, num_l) 
    11 
    12 ## 上面就是map函数的功能,map得到的结果是可迭代对象
    13 print('内置函数map,处理结果', res)
    14 print('内置函数map,处理结果', list(res))
    15 
    16 结果:
    17 [2, 3, 11, 6, 4, 8]
    18 内置函数map,处理结果 <map object at 0x002809F0>
    19 内置函数map,处理结果 [2, 3, 11, 6, 4, 8]
    20 
    21 
    22 map后面的参数是一个可迭代对象,执行map时,相当于执行一个for循环
    23 
    24 print(list(map(lambda x:x 's','12123123')))
    25 #['1s', '2s', '1s', '2s', '3s', '1s', '2s', '3s']
    26 
    27 print(list(map(lambda x:x 's',{'a':1,'b':2})))
    28 # ['as', 'bs']
    

    map函数

    新葡亰496net 60新葡亰496net 61

     1 num_l = [1, 2, 10, 5, 3, 7]
     2 def map_test(func, array):  # func=lambda x:x 1    arrary=[1,2,10,5,3,7]
     3     ret = []
     4     for i in array:
     5         res = func(i)  # add_one(i)
     6         ret.append(res)
     7     return ret
     8 print(map_test(lambda x: x   1, num_l))
     9 
    10 res = map(lambda x: x   1, num_l) 
    11 
    12 ## 上面就是map函数的功能,map得到的结果是可迭代对象
    13 print('内置函数map,处理结果', res)
    14 print('内置函数map,处理结果', list(res))
    15 
    16 结果:
    17 [2, 3, 11, 6, 4, 8]
    18 内置函数map,处理结果 <map object at 0x002809F0>
    19 内置函数map,处理结果 [2, 3, 11, 6, 4, 8]
    20 
    21 
    22 map后面的参数是一个可迭代对象,执行map时,相当于执行一个for循环
    23 
    24 print(list(map(lambda x:x 's','12123123')))
    25 #['1s', '2s', '1s', '2s', '3s', '1s', '2s', '3s']
    26 
    27 print(list(map(lambda x:x 's',{'a':1,'b':2})))
    28 # ['as', 'bs']
    

    map函数

            -注-:

              map()函数不改变原有的 list,而是返回一个新的 list。

             利用map()函数,可以把一个 list 转换为另一个 list,只需要传入转换函数。
    
                   由于list包含的元素可以是任何类型,因此,map() 不仅仅可以处理只包含数值的 list,事实上它可以处理包含任意类型的 list,只要传入的函数f可以处理这种数据类型。
    

     

    新葡亰496net 62新葡亰496net 63

    1 def format_name(s):
    2     # s1=s[0:1].upper() s[1:].lower();
    3     s1 = s.capitalize()
    4     return s1;
    5 
    6 print(map(format_name, ['adam', 'LISA', 'barT']))
    7 print(list(map(format_name, ['adam', 'LISA', 'barT'])))
    

    map实现输入的名字首字母大写

     

           filter函数:

             filter()函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。

    新葡亰496net 64新葡亰496net 65

     1 movie_people=['alex_sb','wupeiqi_sb','linhaifeng','yuanhao_sb']
     2 # def sb_show(n):
     3 #     return n.endswith('sb')
     4 #--->lambda n:n.endswith('sb')
     5 
     6 def filter_test(func,array):
     7     ret=[]
     8     for p in array:
     9         if not func(p):
    10                ret.append(p)
    11     return ret
    12 
    13 res=filter_test(lambda n:n.endswith('sb'),movie_people)
    14 print(res)
    15 
    16 #filter函数
    17 movie_people=['alex_sb','wupeiqi_sb','linhaifeng','yuanhao_sb']
    18 print(filter(lambda n:not n.endswith('sb'),movie_people))
    19 #<filter object at 0x01CFC850>
    20 print(list(filter(lambda n:not n.endswith('sb'),movie_people)))
    21 #['linhaifeng']
    

    filter()函数

             -注-:

                filter()函数对list中的每一个元素带入f函数进行运算,保留返回结构为真的元素。

            reduce函数:

              reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。

     

    新葡亰496net 66新葡亰496net 67

     1 num_l=[1,2,3,100]
     2 def reduce_test(func,array,init=None):
     3     if init is None:
     4         res=array.pop(0)
     5     else:
     6         res=init
     7     for num in array:
     8         res=func(res,num)
     9     return res
    10 
    11 print(reduce_test(lambda x,y:x*y,num_l,100))
    12 
    13 
    14 #reduce函数
    15 # 使用reduce()函数先导入模块
    16 from functools import reduce
    17 num_l=[1,2,3,100]
    18 print(reduce(lambda x,y:x y,num_l,1)) #可以定义起始值,否则默认起始值为第一个元素
    19 print(reduce(lambda x,y:x y,num_l))
    

    reduce()函数

          小结:

     

    新葡亰496net 68新葡亰496net 69

     1 #map()处理序列中的每个元素,得到的结果是一个‘列表’,该‘列表’元素个数及位置与原来一样
     2 #
     3 
     4 #filter遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下来
     5 
     6 people=[
     7     {'name':'alex','age':1000},
     8     {'name':'wupei','age':10000},
     9     {'name':'yuanhao','age':9000},
    10     {'name':'linhaifeng','age':18},
    11 ]
    12 print(list(filter(lambda p:p['age']<=18,people)))
    13 
    14 
    15 #reduce:处理一个序列,然后把序列进行合并操作
    16 from functools import reduce
    17 print(reduce(lambda x,y:x y,range(100),100))
    18 print(reduce(lambda x,y:x y,range(1,101)))
    

    小结

     

     

     
    

        

      

    本文由新葡亰496net发布于奥门新萄京娱乐场,转载请注明出处:内置函数,高阶函数

    关键词:

上一篇:String源码分析,之不可变数据类型

下一篇:没有了