资讯专栏INFORMATION COLUMN

Making Your Python Codes More Functional

gplane / 1830人阅读

摘要:但值得注意的是,因为迭代器中的每个值只能使用一次,就会得到同样语句不同结果的例子见上。生成器模拟考虑一个文件之中出现某个单词例如的句子个数,采用函数式的方法,显然,如下模块模块提供了大量用于操作迭代器的函数。

本篇文章是基于Joel Grus: Learning Data Science Using Functional Python视频的笔记。

常用的函数 currying

在Python中实现科里化的最佳方案是functools.partial。例如以下例子:

# 一般版本
def add1(x): return add(1, x)

# FP的版本
add1_functional = partial(add, 1)
reduce、map、filter

这几个是常见的FP中处理列表的函数,在此不做介绍。

注意:Python这得reducefunctools包中。

iterators(迭代器)

以下是个迭代器的例子:

In [4]: a  = [1,3,4]

In [5]: b = iter(a)

In [6]: next(b)
Out[6]: 1

In [7]: next(b)
Out[7]: 3

In [8]: next(b)
Out[8]: 4

In [9]: next(b)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
 in ()
----> 1 next(b)

StopIteration:

迭代器的特点主要包括:

一次只用一个

只有需要时才会产生数据。

这两个特点保证了其惰性的特点,而另一个好处是我们可以构造无穷序列

generator生成器

生成器所要生成的结果其实就是迭代器,如下:

def lazy_integers(n = 0):
    while True:
        yield n
        n += 1

xs = lazy_integers()

[next(xs) for _ in range(10)]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

[next(xs) for _ in range(10)]
# [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

上面的例子我们可以看出,生成器在此生成了一个无穷长度的序列,由于其惰性我们可以在有限内存之中储存这个无穷序列。
但值得注意的是,因为迭代器中的每个值只能使用一次,就会得到同样语句不同结果的例子(见上)。

一个高阶的用法
squares = (x ** 2 for x in lazy_integers())
doubles = (x * x for x in lazy_integers())

next(squares) #0
next(squares) #1
next(squares) #4

我们发现使用tuple可以直接改变迭代器中的每个元素,这个特性很方便;但值得注意的是,不能写成列表的形式,不然输出值就不为惰性迭代器,就会引起内存外溢。

生成器模拟pipeline

考虑一个文件之中出现某个单词(例如“prime”)的句子个数,采用函数式的方法,显然,如下:

with open("a.txt", "r") as f:
    lines = (line for line in f)
    prime_lines = filter(lambda line: "prime" in line.lower(), lines)
    
    
line_count = len(list(prime_lines))
itertools模块

itertools模块提供了大量用于操作迭代器的函数。

函数名 参数 作用
count [start=0], [step=1] 输出无穷序列(start, start + step, start + 2 * step...)
islice seq, [start=0], stop, [step=1] 输出序列的切片
tee it, [n=2] 复制序列,输出为多个相同序列组成的元组
repeat elem, [n=forever] 重复序列n次,输出为一个repeat元素
cycle p 无限重复cycle里的元素
chain p, q, ... 迭代p里的元素,然后再迭代q的元素,...
accumulate p, [func=add] 返回(p[0], func(p[0], p[1]), func(func(p[0], p[1]), p[2])...)
自定义一些常用的迭代工具
def take(n, it):
    """
    将前n个元素固定转为列表
    """
    return [x for x in islice(it, n)]
    
    
def drop(n, it):
    """
    剔除前n个元素
    """
    return islice(it, n, None)
    

# 获取序列的头
head = next

# 获取除第一个元素外的尾
tail = partial(drop, 1) 

此外,很常见的另一个函数是获得一个递推的迭代器函数,即已知x, f,获得(x, f(x), f(f(x)),...)

def iterate(f, x):
    yield x
    yield from iterate(f, f(x))

注意,要防止mutation,就是说到底复制的是指针还是指针代表的数,显然下面的写法是有问题的:

def iterate(f, x):
    while True:
        yield x
        x = f(x)

一个简单的避免方法是:

def iterate(f, x):
    return accumulate(repeat(x), lambda fx, _:f(fx))
使iterate
def lazy_integers():
    return iterate(add1, 0)

take(10, lazy_integers())
一个例子:斐波那契数列 基本写法
def fib(n):
    if n == 0: return 1
    if n == 1: return 1
    return fib(n - 1) + fib(n - 2)


[fib(i) for i in range(10)]
升级写法——mutable but functional
def fibs():
    a, b = 0, 1
    while True:
        yield b
        a, b = b, a + b
        
take(10, fibs())
Haskell-Like 写法
def fibs():
    yield 1
    yield 1
    yield from map(add, fibs(), tail(fibs()))

take(10, fibs())
尾递归的haskell-like版本
def fibs():
    yield 1
    yield 1
    fibs1, fibs2 = tee(fibs())
    yield from map(add, fibs1, tail(fibs2))

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37811.html

相关文章

  • Awesome JavaScript

    摘要: Awesome JavaScript A collection of awesome browser-side JavaScript libraries, resources and shiny things. Awesome JavaScript Package Managers Loaders Testing Frameworks QA Tools MVC Framew...

    endless_road 评论0 收藏0
  • 在XMLSignature中使用BouncyCastle做RSA

    Abstract There is an article shows demo code for making XMLSignature by using Java XML Digital Signature API, where it actually uses org.jcp.xml.dsig.internal.dom.XMLDSigRI to do DOM formation, and th...

    LiangJ 评论0 收藏0
  • A星(A*)编程指导——用PR2和Python来寻路 (以后翻译)

    Abstract: A Star Algorithm has been widely used in motion planning problems. This article will start from a real project to help you understand the A Star programing idea. It is nice because we will u...

    mengbo 评论0 收藏0
  • Awesome Python II

    摘要: Caching Libraries for caching data. Beaker - A library for caching and sessions for use with web applications and stand-alone Python scripts and applications. dogpile.cache - dogpile.cache...

    lx1036 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<