Skip to main content

A implements of Functional Programming in Python.

Project description

fppy

开发状态:

coverage open-issues close-issues version building

依赖:

Python Python Python

一个基于python的函数式编程类库,仅做学习使用。主要功能如下:

  • 常量定义
  • 惰性求值/惰性属性
  • 抽象代数
  • 常用组合子
  • 列表类
    • 基于Iterable的惰性列表
    • 基于元组定义的列表
    • 基于类定义的列表
    • 基于类从头定义的惰性列表
  • 偏函数
  • 基于性质测试(Property-based Testing)
  • 更多功能的函数装饰器
  • State类
  • 设计模式
    • 错误处理
      • Option类
      • Either类
      • Try类
    • Lens
    • Cake

如何安装

PYPI软件库:

pip install fppy-learn

下载源码自己安装:

pip install poetry

git clone https://github.com/threecifanggen/python-functional-programming.git
cd python-functional-programming

poetry install

快速功能预览

函数修饰器

from fppy.base import F_

@F_
def f(x):
    return x + 1

>>> f(1)
2
>>> f.apply(1)
2
>>> f.and_then(lambda x: x ** 3)(1) # (x + 1) ** 3
8
>>> f.compose(lambda x: x ** 3)(1) # (x ** 3) + 1
1
>>> f.map([1, 2, 3])
[2, 3, 4]

常量定义

>>> from fppy.const import Const
>>>
>>> const = Const()
>>> const.a = 1
>>> const.a
1
>>> const.a = 2
# raise ConstError

列表类

一个可以实现mapreduce等操作的惰性列表

元组实现的列表

1. 新建
from fppy.cons_list_base import *

a = cons_apply(1, 2, 3)
head(a) # 1
tail(a) # cons(2, cons(3, ()))
2. 打印
>>> print_cons(cons_apply(1, 2, 3))
1, 2, 3, nil
3. 列表操作
a = cons_apply(1, 2, 3)
map_cons_curry(lambda x: x + 1)(a) # cons_apply(2, 3, 4)
filter_cons_curry(lambda x: x % 2 == 0)(a) # cons_apply(2)
fold_left_cons_curry(lambda x, y: x + y)(0)(a) # 6

类实现的列表

from fppy.cons_list import Cons

Cons.maker(1, 2, 3)\
    .map(lambda x: x + 1)\
    .filter(lambda x: x % 2 == 0)\
    .fold_left(lambda x, y: x + y, 0)

从头实现的惰性列表

from fppy.lazy_list_base import LazyCons

LazyCons.from_iter(1)(lambda x: x)\
    .map(lambda x: x + 1)\
    .filter(lambda x: x % 2 == 0)\
    .take(3)\
    .fold_left(lambda x, y: x + y, 0)

惰性列表

1. 新建
from fppy.lazy_list import LazyList

# 定义正整数无穷列表
ll = LazyList.from_iter(2)(lambda x: x + 2)

# 从List对象定义
ll = LazyList([1, 2, 3])

# 从生成器、迭代器定义
x = (i for i in range(100))
ll = LazyList(x)
2. map、filter、collect
LazyList([1, 2, 3])\
    .map(lambda x: x + 1)\
    .filter(lambda x: x % 2 == 0)\
    .collect() # 返回[2, 4]
3. 其他

其他方法参考文档。

常见组合子

1. Y组合子

下面的例子是计算阶乘:

from fppy.combinator import Y

fac = Y(lambd f: lambda x: 1 if (x ==0) else x * f(x - 1))

2. Z组合子

下面是计算指数函数的Z组合子实现

from fppy.combinator import Z

power = Z(lambda f: lambda x, n: 1 if (n == 0) else x * f(x, n - 1))

偏函数

这里的偏函数是指Partial Function,即定义域取不完整的函数;而不是高阶函数中的Partial Applied Function的概念。

定义一个如下函数:

  • 如果x > 0,则计算1 / x
  • 如果x < 0,则计算log(-x)
from math import log
from fppy.partail_function import PartialFunction
# 直接定义
pf = PartialFunction\
    .case(lambda x: x > 0)\
    .then(lambda x: 1 / x)\
    .case(lambda x: x < 0)\
    .then(lambda x: log(-x))

## 计算
pf.apply(1) # 返回1
pf.apply(-1) # 返回0
pf.apply(0) # 返回NoOtherCaseError

## 判断是否在某点有定义
pf.is_defined_at(0.4) # 返回True
pf.is_defined_at(0) # 返回False

我们还可以使用or_else来组合偏函数,比如上面的函数可以如下实现:

pf_greater_then_0 = PartialFunction\
    .case(lambda x: x > 0)\
    .then(lambda x: 1 / x)

pf_less_then_0 = PartialFunction\
    .case(lambda x: x < 0)\
    .then(lambda x: log(-x))

pf = pf_greater_then_0.or_else(pf_less_then_0)

惰性求值

1. 惰性属性

from fppy.lazy_evaluate import lazy_property

@dataclass
class Circle:
    x: float
    y: float
    r: float

    @lazy_property
    def area(self):
        print("area compute")
        return self.r ** 2 * 3.14

以上定义了一个圆的类,具体获取area时,仅第一次会计算(通过打印"area compute"显示)。

2. 惰性值

Python没有代码块的概念,所以必须把惰性求值过程包在一个函数内,以下是调用方法:

from fppy.lazy_evaluate import lazy_val

def f():
    print("f compute")
    return 12

lazy_val.a = f

调用结果下:

>>> lazy_val.a
f compute
12
>>> lazy_val.a
12

这就表示仅第一次调用时发生了计算。

错误处理

1. Option

from fppy.option import Just, Nothing

>>> Just(1).map(lambda x: x + 1)
Just(2)
>>> Just(1).flat_map(lambda x: Just(x * 3))
Just(3)
>>> Just(1).get
1
>>> Just(1).get_or_else(2)
1
>>> Just(1).filter(lambda x: x < 0)
Nothing()
>>> Just(1).filter(lambda x: x > 0)
Just(1)

与偏函数合用会有很多妙处:

from math import log
from fppy.partail_function import PartialFunction

pf = PartialFunction\
    .case(lambda x: x > 0)\
    .then(lambda x: 1 / x)\
    .case(lambda x: x < 0)\
    .then(lambda x: log(-x))


>>> pf.lift(1)
Just(1)
>>> pf.lift(0)
Nothing()
>>> Just(1).collect(pf)
Just(1)
>>> Just(0).collect(pf)
Nothing()

>>> Just(1).collect(pf)
Just(1.)
>>> Just(1).collect(pf).map(lambda x: int(x) - 1)
Just(-1)
>>> Just(1).collect(pf).map(lambda x: int(x) - 1).collect(pf)
Just(0)
>>> Just(1).collect(pf).map(lambda x: int(x) - 1).collect(pf).collect(pf)
Nothing()
>>> Just(1).collect(pf).map(lambda x: int(x) - 1).collect(pf).collect(pf).collect(pf)
Nothing()
>>> Just(1).collect(pf).map(lambda x: int(x) - 1).collect(pf).collect(pf).collect(pf).get_or_else(2)
2

2. Either

(待完善)

3. Try

Try单子时一个非常方便地处理错误的类,它的逻辑时传递错误类一直到最后处理,可以获取到错误发生时的错误类型和输入值,方便调试:

>>> from fppy.try_monad import Try
>>> res = Try(1).map(lambda x: x / 0).map(lambda x: x + 1)
>>> res.error
ZeroDivisionError('division by zero')
>>> res.get_or_else(2)
2
>>> res.get_error_input()
1

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fppy_learn-0.3.1.tar.gz (20.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fppy_learn-0.3.1-py3-none-any.whl (24.7 kB view details)

Uploaded Python 3

File details

Details for the file fppy_learn-0.3.1.tar.gz.

File metadata

  • Download URL: fppy_learn-0.3.1.tar.gz
  • Upload date:
  • Size: 20.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.3.1 CPython/3.10.9 Linux/5.15.0-1024-azure

File hashes

Hashes for fppy_learn-0.3.1.tar.gz
Algorithm Hash digest
SHA256 08aa55401f9fb0e1cc18f737a38709c57d17cca8a98a52f717942a410924bb83
MD5 67a0426d133a9fb37fdd34cf20b46fee
BLAKE2b-256 81f6105aae055eeb46aff542eb348f6a0e5f94adf158dbd62db31545fa67fbbe

See more details on using hashes here.

File details

Details for the file fppy_learn-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: fppy_learn-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 24.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.3.1 CPython/3.10.9 Linux/5.15.0-1024-azure

File hashes

Hashes for fppy_learn-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 bddc8a3e436198ff4e6500baa7b521d4a6cdefdc37c4454c1febac9c94816f4a
MD5 024fbc170702659e6e1a62aa2721ac2e
BLAKE2b-256 65a3e816ffa44c2d7f0001b69870ca6f7434727513b49bbc5c981d3ee375f025

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page