
Security News
New CVE Forecasting Tool Predicts 47,000 Disclosures in 2025
CVEForecast.org uses machine learning to project a record-breaking surge in vulnerability disclosures in 2025.
开发状态:
依赖:
一个基于python
的函数式编程类库,仅做学习使用。主要功能如下:
Iterable
的惰性列表从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
一个可以实现map
、reduce
等操作的惰性列表
from fppy.cons_list_base import *
a = cons_apply(1, 2, 3)
head(a) # 1
tail(a) # cons(2, cons(3, ()))
>>> print_cons(cons_apply(1, 2, 3))
1, 2, 3, nil
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)
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)
LazyList([1, 2, 3])\
.map(lambda x: x + 1)\
.filter(lambda x: x % 2 == 0)\
.collect() # 返回[2, 4]
其他方法参考文档。
下面的例子是计算阶乘:
from fppy.combinator import Y
fac = Y(lambd f: lambda x: 1 if (x ==0) else x * f(x - 1))
下面是计算指数函数的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)
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"
显示)。
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
这就表示仅第一次调用时发生了计算。
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
(待完善)
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
FAQs
A implements of Functional Programming in Python.
We found that fppy-learn demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
CVEForecast.org uses machine learning to project a record-breaking surge in vulnerability disclosures in 2025.
Security News
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.
Research
Security News
Eight new malicious Firefox extensions impersonate games, steal OAuth tokens, hijack sessions, and exploit browser permissions to spy on users.