高阶python 函数式编程

高阶python 函数式编程

- 函数式

函数式编程(FunctionalProgramming)

- 基于lambda演示得一种编程方式

    - 程序中只有函数

    - 函数可以做为参数,作为返回值,

    - 纯函数式编程语言 : LISP,Haskell

- python函数式编程只是借鉴函数式编程得一些特点,可以理解成一半函数式一半python

- 需要讲述

    - 高阶函数 :把函数作为参数使用得函数,叫高阶函数;

    - 返回函数 :把函数做为返回值得函数,叫返回函数;

    - 装饰器 :就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能;

    - 偏函数 :

### lambda 表达式

- 函数:最大程度复用代码

- lambda表达式(匿名函数)

    - 一个表达式,没有方式名称

```python

# 定义一个返回函数,返回fun2。通过变量fun进行接收返回值,打印返回值类型,并调用返回函数。

def fun(a):

    def fun2():

        print "this is fun2"

    print a

    return fun2

fun = fun(2)

print (type(fun))

print fun()

```

系统高阶函数 - map

- 原意就是映射,即把集合或列表得元素,每一个元素都按照一定规则进行操作,生成一个新的列表或者集合

- map函数是系统提供得具有映射功能得函数,返回值是一个迭代对象

- map python2 传入什么类型数据返回什么类型数据

- map python3 传入什么类型数据返回 ..."map"... 类型数据

- map(...)

    map(function, sequence[, sequence, ...]) -> list


    Return a list of the results of applying the function to the items of

    the argument sequence(s).  If more than one sequence is given, the

    function is called with an argument list consisting of the corresponding

    item of each sequence, substituting None for missing values when not all

    sequences have the same length.  If the function is None, return a list of

    the items of the sequence (or a list of tuples if more than one sequence).

```python

# 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 (l3)

```

 reduce

- 意愿是归并,缩减

- 把一个可迭代的对象最后归并成一个结果

- 对于函数参数要求:必须有两个参数,必须有返回结果

- reduce[1,2,3,4,5] = fun(fun(fun(fun(1,2),3),4),5)

- reduce 需要 functools包

```python

from functools import reduce

# 定义个操作函数

def add(x,y):

    return x + y

# 对于列表【1,2,3,4,5,6】执行add 操作

rst = reduce(add ,[1,2,3,4,5,6])

print (rst)

# 以上reduce可看作下面进行运算

rst2 =add(add(add(add(add(1,2),3),4),5),6)

print(rst2)

```

filter 函数

- 过滤函数:对一组数据进行过滤,符合条件的数据会生成一个新的列表并返回

- 跟map 相比:

    - 相同: 都对列表的每一个元素逐一进行操作

    - 不同: map会生成一个跟原来数据相对应的新队列

          filter 不一定,只要符合条件的才会进入新的数据集合

    - filter函数怎么写:

        - 利用给定函数进行判断

        - 返回值一定是个布尔值

        - 调用格式:filter(f,data),f是过滤函数,data是数据

```python

# filter 函数

# 对一个列表,对其进行过滤,偶数组成一个新列表

# 需要定义过滤函数

# 过滤函数要求有输入,返回布尔值

def isEven(a):

    return a % 2 == 0

l = [1,2,3,4,54,3,2,32,32,32,3,333,44,32,4325]

res = filter(isEven,l)

#返回一个可迭代对象

print(res)

print([i for i in res])

```

 高阶函数-排序

- 把一个序列按照给定的算法进行排序

- key: 在排序中对每一元素进行key函数运算,可以理解成按照key函数定义的逻辑进行排序

- python2 和 python3 相差巨大

```python

#排序案例1

a = [12,32,43,543,56,654,6576,5765,765,645,6546645,654645]

al = sorted(a)

ad = sorted(a,reverse=True)

print(al)

print(ad)

```

```python

#排序案例2

a = [-12,2,32,-455,321,32]

# 按照绝对值进行排序

# abs是求绝对值的意思

# 即按照绝对值的倒叙进行排序

al = sorted(a, key=abs, reverse=True)

print(al)

```

```python

#sorted 排序案例

astr = ['dana','whj','jin','WTt','Zs','sz']

str1 = sorted(astr)

print(str1)

str2 = sorted(astr,key=str.lower)

print(str2)

```

 高阶函数-返回函数

```python

# 负责一点的返回函数的例子

# args 参数列表

# myF4 定义函数,返回内部定义的函数myF5

# myF5使用了外部变量,这个变量是myF4的参数

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,7,8,9,10)

f5()

```

```python

f6 = myF4(10,20,30)

f6()

```

闭包(closure)

- 当一个函数在内部定义函数,并且内部的函数应用外部函数的参数或局部变量,当内部函数被作返回值的时候,相关参数和变量保存在返回的函数中,这种结果,叫做闭包。

- 上面定义的myF4 是一个标准的闭包结构

```python

# 闭包常见的坑

def count():

    # 定义列表

    fs = []

    for i in range(1,4):

        # 定义了一个函数f

        def f():

            return i*i

        fs.append(f)

    return fs

f1,f2,f3 = count()

print(f1())

print(f2())

print(f3())

```

### 出现问题:

- 造成上述情况的原因是,返回函数引用了变量i,i并非立即执行,而是等到三个函数都返回的时候才统一执行,此时i已经变成了3,最终调用的时候,都返回的3*3

- 此问题描述成:返回闭包时,返回函数不能引用任何循环变量

- 解决方案:在创建一个函数,用该函数的参数绑定循环变量的当前值,无论该循环变量以后如何改变,已经绑定的函数参数值不在改变

```python

# 修改上述函数

def count1():

    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 = count1()

print(f1())

print(f2())

print(f3)

```

装饰器(Dercrator)

- python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数

- 在不改动函数代码的基础上无限制扩展函数功能的一种机制,本质上讲,装饰器是一个返回函数的高阶函数

- 装饰器使用:使用@语法,即在每次要扩展到函数定义前面使用@+函数名

- 装饰器先执行装饰器内函数,在执行被装饰函数。

```python

# 我们要想拓展原来函数代码,最直接的办法就是侵入代码里面修改,例如:

import time

def hello():

    startTime = time.time()

    print("hello")

    time.sleep(1)

    print("world")

    endTime = time.time()

    msecs = (endTime - startTime)*1000

    print("time is %d ms" %msecs)

hello()

```

- 避免直接侵入原函数修改,但是生效需要再次执行函数

```python

import time

def deco(func):

    startTime = time.time()

    func()

    endTime = time.time()

    msecs = (endTime - startTime)*1000

    print("time is %d ms" %msecs)

def func():

    print("hello")

    time.sleep(1)

    print("world")

f = func

deco(f)#只有把func()或者f()作为参数执行,新加入功能才会生效

```

- 核心代码区域有一千万个func()函数,从func01()到func1kw(),按以上实现方案,想要拓展这一千万个函数功能,就是要执行一千万次deco()函数。这种方式不可取。

- 实现一个最简陋的装饰器,不使用任何语法和高级语法,看看装饰器最原始的面貌

- 这里的deco函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。其中作为参数的这个函数func()就在返回函数wrapper()的内部执行。然后在函数func()前面加上@deco,func()函数就相当于被注入了计时功能,现在只要调用func(),它就已经变身为“新的功能更多”的函数了。

- 所以这里装饰器就像一个注入符号:拓展了原来函数的功能既不需要侵入函数内更改代码,也不需要重复执行原函数。

```python

#既不需要侵入,也不需要函数重复执行

import time

def deco(func):

    def wrapper():

        startTime = time.time()

        func()

        endTime = time.time()

        msecs = (endTime - startTime)*1000

        print("time is %d ms" %msecs)

    return wrapper

# 上面定义装饰器,使用的时候需要用到@ ,此符号是python的语法糖

@deco

def func():

    print("hello")

    time.sleep(1)

    print("world")

f = func #这里f被赋值为func,执行f()就是执行func()

f()

```

- 带有参数的装饰器

```python

import time

def deco(func):

    def wrapper(a,b):

        startTime = time.time()

        func(a,b)

        endTime = time.time()

        msecs = (endTime - startTime)*1000

        print("time is %d ms" %msecs)

    return wrapper

@deco

def func(a,b):

    print("hello,here is a func for add :")

    time.sleep(1)

    print("result is %d" %(a+b))

f = func

f(3,4)

```

- 带有不定参数的装饰器

```python

import time

def deco(func):

    def wrapper(*args, **kwargs):

        startTime = time.time()

        func(*args, **kwargs)

        endTime = time.time()

        msecs = (endTime - startTime)*1000

        print("time is %d ms" %msecs)

    return wrapper

@deco

def func(a,b):

    print("hello,here is a func for add :")

    time.sleep(1)

    print("result is %d" %(a+b))

@deco

def func2(a,b,c):

    print("hello,here is a func for add :")

    time.sleep(1)

    print("result is %d" %(a+b+c))

f = func

func2(3,4,5)

f(3,4)

```

- 多个装饰器

```python

import time

def deco01(func):

    def wrapper(*args, **kwargs):

        print("this is deco01")

        startTime = time.time()

        func(*args, **kwargs)

        endTime = time.time()

        msecs = (endTime - startTime)*1000

        print("time is %d ms" %msecs)

        print("deco01 end here")

    return wrapper

def deco02(func):

    def wrapper(*args, **kwargs):

        print("this is deco02")

        func(*args, **kwargs)

        print("deco02 end here")

    return wrapper

@deco01

@deco02

def func(a,b):

    print("hello,here is a func for add :")

    time.sleep(1)

    print("result is %d" %(a+b))

f = func

f(3,4)

```

 偏函数(Partial)

- 参数固定的函数,相当于一个由特定参数的函数体

- functools.partial的作用是:把一个函数某些函数固定,返回一个新函数

```python

# 把字符串转换十进制数字

int("12345")

# 求八进制的字符串12345,表示成十进制的数字是多少

int("12345",base=8)

```

```python

# 新建一个函数,此函数是默认输入的字符串是16进制数字

# 把此字符串返回十进制的数字

def int16(x,base=16):

    return int(x,base)

int16("12345")

```

```python

import functools

int16 = functools.partial(int,base=16)

int16("12345")

```

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容