Python3函数式编程

来源:互联网 发布:淘宝运费模块名称 编辑:程序博客网 时间:2024/05/16 08:10

python3手册的目录

Python与函数式编程

Python的函数式不是特别有名, 但是我们还是可以做一些函数式编程的.

Python目前没有内置的不可变集合类库像Clojure设计的那样优秀. Clojure的不可变的集合不仅在修改的时候对内存的利用率很高, 并且很适合多线程直接传递数据. 避免加锁.

下面介绍的函数式编程使用的是Python3内建的集合类, 在多线程之间传递时, 我们要做好加锁工作. 或者做深度拷贝. 或者我们将对共享资源的访问给一个线程来操作, 其他线程通过queue模块来给操作资源的那个线程发送命令. queue的使用示例: Python3多线程编程

下面的方式不叫函数式编程

下面的方式中, 函数increment使用了外部的变量a, 因此有副作用

a = 0def increment():    global a    a += 1

下面的方式是函数式编程

def increment(a):    return a + 1

什么是函数式编程

函数式编程是一种编程模式, 它避免使用可变数据类型, 避免状态的改变. 流行的函数式语言有: Lisp, Haskell, Clojure.

函数式语言是描述型语言的子集. 描述型语言区别于命令型语言(c/c++,go,java)

函数式语言的特点

  • 避免用全局状态的来解决问题
  • 使用不可变数据类型(最好设计成内存使用率高的方式)
  • 在语言中, 函数是一等公民(像java就不是)
  • 使用高阶函数
  • 使用递归函数

前两条主要是用来消除副作用. 如果状态的变更不依赖于输入函数的输入, 那么查找bug会是很麻烦是事情.

状态的表示和转移

在函数式编程中, 函数将输入转变成输出, 不产生和维护中间状态.
我们来看看下面的例子:

def square(x):    return x*xinput = [1, 2, 3, 4]output = []for v in input:    output.append(square(v))
def square(x):    return x*xinput = [1, 2, 3, 4]output = map(square, input)

以上两段代码完成的任务是一样的. 但是我们可以看到, 第二种没有中间状态. 第一种在执行的时候, output 变量一直在改变, 并且是可以被其他线程访问到的. 但是第二种不改变input也不产生中间状态, 只有计算完后, 才输出output变量.

一等公民的函数, 和高阶函数

在Python我们可以直接定义一个函数, 然后使用它, 不像Java, 必须有一个对象或者类的前提下才能使用函数.

def greet(name):    print("Hello %s!" % name)say_hello = greetsay_hello('World')# Hello World!

高阶函数, 就是把函数作为参数的函数, 或者返回一个函数的函数.
比如Python中的内建函数map()

reduce() 以及 filter()

reduce函数将一个序列的数据, 归结为一个输出.

from functools import reducesum = reduce(lambda a, x: a + x, [0, 1, 2, 3, 4])

filter函数将一个序列中的每个元素进行筛选, 并且返回一个新的序列

def is_odd(n):   return n%2 == 1print(is_odd(2))# Falseprint(is_odd(3))# Truevalues = [1, 2, 3, 4, 5, 6]result = filter(is_odd, values)print(list(result))# [1, 3, 5]

生成器以及懒赋值

在Python中, 生成器Generator Functions和生成器表达式Generator Expressions他们的行为都跟迭代器一样. 好处就是不必预先将整个数据序列计算出来并且放入内存. 只是需要再使用的时候才去计算, 用多少计算多少call-by-need strategy.
下面的图为 generator iterator iterable container 之间的关系.
generator+iterator+iterable+container

代码示例

下面的例子默认: from funcs import seq
使用了链式调用, 类似 Kotlin 的风格

例子1:
对一个序列进行循环迭代, 然后只取前10个元素, 最后将取到的10个元素保存到list中. 这里不到最后的list()调用, 是不会将整个结果生成到内存中的. 这样对于需要大量的数据进行迭代的应用来说, 效率很高, 对内存很友好.a =seq([1, 22, 3, 45]).cycle().head(10).list()print(a)输出: [1, 22, 3, 45, 1, 22, 3, 45, 1, 22]
例子2:
将多个序列合并a = seq([1, 22, 3, 45]).chain([1, 2, 4, 5, 2], [5, 65, 6, 90])print(list(a))输出: [1, 22, 3, 45, 1, 2, 4, 5, 2, 5, 65, 6, 90]
例子3:
对序列进行求平方, 再过滤出大于5的列表, 最后对列表进行求和, 求和的初始值为0. 也就是说, sum的初始值为0, x从filter()产出的列表的第一个元素开始遍历.a = seq([1, 2, 3, 4, 5]).map(lambda x: x ** 2).filter(lambda x: x > 5).reduce(lambda sum, x: sum + x, 0)print(a)输出: 50

funcs.py 模块

import collectionsfrom functools import reducefrom array import arrayimport itertoolsclass seq:    def last_index(self):        t = list, array, str, tuple, bytes        if isinstance(self.data, t):            return len(self.data) - 1        else:            raise TypeError(f"{type(self.data)} is not instance of {t}")    def size(self):        t = collections.Sized,        if isinstance(self.data, t):            return len(self.data)        raise TypeError(f"{type(self.data)} is not instance of {t}")    def __init__(self, _s):        t = collections.Iterable,        if isinstance(_s, t):            self.data = _s        else:            raise TypeError(f"{type(_s)} is not instance of {t}")    def __iter__(self):        return iter(self.data)    def map(self, f):        return seq(map(f, self.data))    def filter(self, f):        return seq(filter(f, self.data))    def reduce(self, f, init=None):        return reduce(f, self.data, init)    def zip(self, *iter):        return seq(zip(self.data, *iter))    def cycle(self):        return seq(itertools.cycle(self.data))    def chain(self, *iter):        return seq(itertools.chain(self.data, *iter))    def list(self):        return list(self)    def head(self, n=10):        def gen():            nonlocal n            for d in self:                if n <= 0:                    break                n -= 1                yield d        return seq(gen())
参考:

Functional Programming in Python
A practical introduction to functional programming

原创粉丝点击