这篇文章将深入详细地介绍 Python 反应式编程 |
反应式编程介绍
反应式编程(Reactive programming):是一种基于数据流(data stream)和变化传递(propagation of change)的声明式(declarative)的编程规范。
换句话说,就是使用异步数据流进行编程,这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。
反应式编程最著名的实现是 ReactiveX,其为 Reactive Extensions 的缩写,一般简写为 Rx
☕️ Rx组成
Rx有5部分组成:
- Observable:被观察者或者叫数据发射源,可以被观察者订阅,被观察者会将数据 push 给所有的订阅者
- Observer/Subscriber:观察者或者订阅者,接收 Observable 推送的数据
- Subscribe:订阅操作,把观察者订阅到 Observable 中
- Operators:操作符,以对数据流进行各种操作,包括创建、转换、过滤、组装、合并、筛选等等
- Schedulers:调度器,是 Rx 的线程池,可以指定线程池来操作中执行的任务。我们可以通过 subscribe_on 来指定 Observable 的任务在哪个线程池中执行,也可以通过 subscribe_on 来指定订阅者/观察者们在哪个线程执行
观察者(observer) 包含三个基本函数:
- no_next():基本事件,用于传递项。
- no_completed():事件队列的全部事件都完结。当不会再有新的 on_next() 发出时,需要触发 on_completed() 方法作为标志。
- on_error():事件队列异常。在事件处理过程中出异常时,on_error() 会被触发,会发出错误消息,同时队列自动终止,不允许再有事件发出
注意:在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。如果在队列中调用了其中一个,就不应该再调用另一个。 |
命令式编程和反应式编程的区别:
- 命令式编程,重视控制(执行过程),以运算、循环、条件判断、跳转来完成任务,计算机为先的思维,指令驱动机器做事,容易引入大量状态变量
- 反应式编程,重视任务的解决(执行结果),关注数据转换和转换的组合,属于人脑思维、任务驱动、分治的类型,有明确的输入和输出状态
Rx 的操作
Rx 的所有操作都是基于操作符 Operator 的,换句话说,操作符是 Rx 的核心。操作符又分为:创建操作符、转换操作符、过滤操作符、合并操作符等等,下面我们通过操作符来介绍 Rx 所支持的各种操作。
这里使用的 Rx 库版本为 RxPy 1.6.x |
📝 创建 Observable
我们先以一个代码为例来讲解如何创建 Observable
from rx import Observable, Observer
def push_five_strings(observer):
"""
订阅函数,用于调用观察者的 on_next、on_completed、on_error 方法
"""
observer.on_next("Alpha")
observer.on_next("Beta")
observer.on_next("Gamma")
observer.on_next("Delta")
observer.on_next("Epsilon")
observer.on_completed()
class PrintObserver(Observer):
"""
继承Observer重写观察者的 on_next、on_completed、on_error 方法
"""
def on_next(self, value):
print("Received {0}".format(value))
def on_completed(self):
print("Done!")
def on_error(self, error):
print("Error Occurred: {0}".format(error))
# 创建 Observable 对象
source = Observable.create(push_five_strings)
# 订阅观察者
source.subscribe(PrintObserver())
>>>>>
Received Alpha
Received Beta
Received Gamma
Received Delta
Received Epsilon
Done!
在这个例子中,使用的是 create 操作符来创建 Observable。create 操作符需要提供一个订阅函数,比如例子中的 push_five_strings(observer),这个订阅函数会接收一个观察者对象(observer),在订阅函数体里面通过调用 observer 对象的 on_next 方法来发射数据、通过调用 on_completed 方法来通知所有数据发射完成以及通过调用 on_error 方法来通知数据出错。创建完成后返回一个 Observable 对象 source,然后调用 Observable 对象的 subscribe 方法订阅一个观察者对象到 Observable 序列中,这个观察者对象就是类 PrintObserver 的一个实例对象 PrintObserver()。
一旦创建并订阅成功后,Observable 将会把观察者对象传给订阅函数 push_five_strings,然后执行订阅函数,在订阅函数里面连续调用了5次观察者的 on_next() 函数,并提供一个字符串作为数据值,最后调用观察者的 on_completed() 方法结束整个流程。
如果数据源是可以迭代的对象,我们还可以使用 from_ 操作符来创建 Observable 对象。from_ 操作符的功能就是把一些可迭代的对象或数据转换为一个 Observable 对象,比如:
from rx import Observable, Observer
class PrintObserver(Observer):
"""
继承Observer重写观察者的 on_next、on_completed、on_error 方法
"""
def on_next(self, value):
print("Received {0}".format(value))
def on_completed(self):
print("Done!")
def on_error(self, error):
print("Error Occurred: {0}".format(error))
# 创建 Observable 对象
source = Observable.from_(["Alpha", "Beta", "Gamma", "Delta", "Epsilon"])
# 订阅观察者
source.subscribe(PrintObserver())
>>>>>
Received Alpha
Received Beta
Received Gamma
Received Delta
Received Epsilon
当然,我们还可以使用 1 到 3 个 lambda 函数来替代观察者对象:
from rx import Observable
source = Observable.from_(["Alpha", "Beta", "Gamma", "Delta", "Epsilon"])
source.subscribe(on_next=lambda value: print(