您的位置:首页 > 编程语言 > Python开发

python 的高级特性:函数式编程,lambda表达式,装饰器

2019-06-26 09:01 489 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_40421176/article/details/93708650

一、Python语言的高级特性

函数式编程

  • 基于Lambda演算的一种编程方式 程序中只有函数
  • 函数可以作为参数,同样可以作为返回值
  • 纯函数式编程语言:LISP,Haaskell
  • Python函数式编程只是借鉴函数式编程的一些特点,可以理解成一半函数式一半Python
  • 需要讲述
      高阶函数
    • 返回函数
    • 匿名函数
    • 装饰器
    • 偏函数

    二、lambda表达式

    • 函数:最大程度上复用代码 存在问题:如果函数很小,反而觉得麻烦
    • 如果函数被调用次数少,则造成浪费
    • 对于读者来说,造成阅读流程被迫中断

    lambda表达式(匿名函数)

    • 一个表达式,函数体相对简单
    • 不是一个代码块,仅仅是一个表示式
    • 可以有一个或多个参数,用逗号隔开
      lambda表达式的用法
      1、以lambda开头
      2、紧跟一定的参数(如果有的话)
      3、参数后用冒号和表达式主题隔开
      4、只是一个表达式,没有return
    #lambda表达式的用法
    stm = lambda x: 100 * x
    a = stm(12)
    print(a)
    stm2 = lambda x,y,z: x+10*y+100*z
    b = stm2(4,5,6)
    print(b)

    三、高阶函数

    • 把函数作为参数使用的函数,叫做高阶函数 函数名称就是一个变量
    • 既然函数名称是变量,则应该可以被当做参数传入另一个函数
    #函数名称就是一个变量
    def funA():
    print("In funA")
    funB = funA
    funB()
    def funC(n):
    return n * 100
    
    #在写一个函数,把传入参数乘以300倍
    def funD(n):
    return funC(n) * 3
    print(funD(9))
    
    #写一个高阶函数
    def funE(n,f):
    return f(n) * 3
    print(funE(9,funC))

    四、系统高阶函数

    1、map

    • 原意就是映射,即把集合或者列表的元素,每一个元素都按照一定的规则进行操作,生成一个新的列表或者集合
    • map函数是系统提供的具有映射功能的函数,返回值是一个迭代对象
    #由一个列表,相对每个元素都乘以10,得到新的列表
    l1 = [i for i in range(10)]
    print(l1)
    l2 = []
    for i in l1:
    l2.append(i * 10)
    print(l2)
    #利用map实现
    def mulTen(n):
    return n * 10
    l3 = map(mulTen,l1)
    print(type(l3))
    #map类型是一个可迭代的结构
    print(l3)
    for i in l3:
    print(i)

    2、reduce

    • 原意是归并,缩减
    • 把一个可迭代对象最后归并成一个结果
    • 对于作为参数的函数要求,必须有两个参数,必须有返回结果
    • reduce需要导入functools包
    from functools import reduce
    def Add(x,y):
    return x+y
    a = reduce(Add,[1,2,3,4,5])
    print(a)

    3、filter函数

    • 过滤函数:对一组数据进行过滤,符合条件的数据会生成一个新的列表并返回
    • 与map的比较 相同
      都是对列表的每个元素进行操作 不同
      1、map会生成一个跟原来数据相对应的新队列
      2、filter不一定,只有符合条件的才会进入新队列
  • filter函数怎么写
      利用给定函数进行判断
    • 返回值一定是一个布尔值
    • 调用格式
    filter(fun,date),fun是过滤函数,date是数据
    #定义过滤函数#要求有输入,返回布尔值
    def isEven(a):
    return a % 2 == 0
    l = [3,4,5,12,45,14,3,11,51]
    rst = filter(isEven, l)
    print(type(rst))
    print(rst)
    print([i for i in rst])

    五、高阶函数-排序

    • 把一个序列按照给定算法就行排序
    • key:在排序前对每一个元素进行key函数运算,可以理解成按照kay函数定义的逻辑进行排序
    • python2和python3相差巨大
    • sorted函数
      格式:
      sorted(a,reverse),a是要进行排序的数据,reverse是正序或倒序的参数
      reverse为False时为正序排列,为True时为倒序排列
      默认reverse为False
    a = [12,4,5,6,8,54,587,422,4679,52]
    al = sorted(a)
    print(al)
    al1 = sorted(a,reverse = True)
    print(al1)
    b = [12,-54,23,-5,5,48,-65,74,-78]
    #按照绝对值进行排序#abs是求绝对值的意思
    b1 = sorted(b,key=abs)
    print(b1)
    #字符串排序
    c = ['da','Da','fdsf','dfc','EFxc','Erv']
    c1 = sorted(c)
    print(c1)
    c2 = sorted(c,key=str.lower)
    print(c2)

    六、返回函数

    • 函数可以返回具体的值
    • 也可以返回一个函数作为结果
    #定义一个普通函数
    def myF(a):
    print('In myF')
    return None
    a = myF(2)
    print(a)
    #函数作为返回值返回,被返回的函数在函数体内定义
    def myF2():
    def myF3():
    print('In myF3')
    return 3
    return myF3
    f3 = myF2()
    print(type(f3))
    print(f3)
    f3()
    print(f3())
    #复杂一点的返回函数的例子d
    def myF4(*args):
    def myF5():
    rst = 0
    for n in args:
    rst += n
    return rst
    return myF5
    f5 = myF4(1,2,3,4,5,6)
    print(f5())

    七、闭包(closure)

    • 当一个函数在内部定义函数,并且内部函数应用外部函数的参数或者局部变量,当内部函数被当做返回值的时候,相关参数和变量保存在返回的函数中,这种结果叫做闭包
    • 上例中的myF4就是一个标准的闭包
    #闭包常见的坑
    def count():
    fs = []
    for i in range(1,4):
    #定义一个函数f
    #f是一个闭包结构
    def f():
    return i*i
    fs.append(f)
    return fs
    f1,f2,f3 = count()
    print(f1())
    print(f2())
    print(f3())
    • 上例中的问题
      1、出现的问题:
      造成上述问题的原因是返回函数引用了变量i,i并非立即执行,而是等到三个函数都返回的时候才统一使用,此时i已经变成了3,所以返回的都是3*3
      所以,返回闭包时返回函数不能引用任何循环变量
      2、解决方案:
      再创建一个函数,用该函数的参数绑定循环变量的当前值,无论该循环变量以后怎么改变,已经绑定的函数参数值不在改变

    如下

    def count():
    def f(j):
    def g():
    return j*j
    return g
    fs = []
    for i in range(1,4):
    fs.append(f(i))
    return fs
    f1,f2,f3 = count()
    print(f1())
    print(f2())
    print(f3())

    八、装饰器

    • 一个普通的函数
    def hello():
    print('hello')
    return None
    hello()
    f = hello
    f()
    print(id(f))
    print(id(hello))
    #上述说明f和hello是同一个函数,也可以用以下方法验证
    print(f.__name__)
    print(hello.__name__)
    • 现在有新的需求,对hello的功能就行扩展,每次打印hello之前打印当前系统时间,实现这个功能又不能改变现有代码
    • 这是就是用装饰器
    • 1、装饰器定义: 在不改动函数代码的基础上无限制扩展函数功能的一种机制,本质上讲,装饰器是一个返回函数的高阶函数
  • 2、装饰器的使用
      使用@语法,即在每次要扩展到函数定义千使用@+函数名
    • 实现对hello的扩展的案例
    import time
    #高阶函数,以函数作为参数
    def printTime(f):
    def wrapper(*args,**kwargs):
    print("Time:",time.ctime())
    return f(*args,**kwargs)
    return wrapper
    #上面定义了装饰器,使用的时候需要用到@,此符号是python的语法糖
    @printTime
    def hello():
    print("Hello")
    hello()
    @printTime
    def hello2():
    print('hahah')
    hello2()
    • 3、装饰器的好处 一次定义,可以装饰任何函数
    • 一旦被其装饰,则把装饰器的功能直接添加到定义函数的功能上
    • 而且不用改动定义函数的代码,非常安全,绿色
  • 4、案例中对函数的装饰使用了系统定义的语法糖
  • 九、偏函数

    • 参数固定的函数,相当于一个有特定参数的函数体-
    • 需要使用funtools.partial模块
    • 其作用是把一个函数某些参数固定,返回一个新函数
    import functools
    int16a = functools.partial(int,base=16)
    b = int16a('a')
    print(b)
    help(int)

    十、高级函数补充

    1、zip

    • 把两个可迭代的内容生成一个可迭代的tuple元素类型组成的内容
    l1 = [1,2,3,4,5]
    l2 = [11,22,33,44,55]
    z = zip(l1,l2)
    print(type(z))
    print(z)
    for i in z:
    print(i)

    2、enumerate

    • 跟zip功能比较像
    • 对可迭代的对象里的每一个元素,配上一个索引,然后索引和内容构成tuple类型
    l2 = [11,22,33,44,55]
    em = enumerate(l2)
    l = [i for i in em]
    print(l)
    em1 = enumerate(l2,start=100)
    ll = [i for i in em1]
    print(ll)

    3、collections模块

    • namedtuple
    • deque

    1、namedtuple

    • tuple 类型
    • 是一个可命名的tuple
    import collections
    Point = collections.namedtuple("Point",['x','y'])
    p = Point(11,22)
    print(p.x)
    print(p[0])
    
    Circle = collections.namedtuple('Ciecle',['x','y','r'])
    c = (100,150,50)
    print(c)
    print(type(c))
    #检测namedtuple是否为tuple的子类
    isinstance(c,tuple)

    2、deque

    • 比较方便的解决频繁删除插入带来的效率问题
    from collections import deque
    q = deque(['a','b','c'])
    print(q)q.append('d')
    print(q)
    #从前面插入
    q.appendleft('x')
    print(q)

    3、defaultdict

    • 当直接读取dict不存在的属性时,直接返回默认值
    from collections import defaultdict
    d = {'one':1,'two':2,'three':3}
    print(d['one'])
    #print(d['four'])
    func = lambda:'杨朔'
    d1 = defaultdict(func)
    d1['one'] = 1
    d1['two'] = 2
    print(d1['one'])
    print(d1)
    print(d1['four'])

    4、Counter

    • 统计字符串的个数
    from collections import Counter
    c = Counter('ksdcs,,csddscdsojdsvm,z.')
    #为什么下面不把ksdcs,,csddscdsojdsvm,z.作为键值,而是以其中每一个字符作为键值#这是因为需要括号里的内容为可迭代的
    print(c)
    s = ('aa','dd','aa','dd','df','sd','aa')
    ss = Counter(s)
    print(ss
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: