1

我有一个错误,它不小心将 anObservable用作可迭代对象。对于大多数对象,这通常很容易检测到:

>>> tuple(object())

Traceback (most recent call last):
  File "C:\Program Files (x86)\Python27\lib\site-packages\IPython\core\interactiveshell.py", line 3035, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-4-40e3dfc60da8>", line 1, in <module>
    tuple(object())
TypeError: 'object' object is not iterable

然而,对于一个 Rx observable,它会默默地使 Python 崩溃:


MWE:

from rx import Observable

observable = Observable.from_list([1,2,3])
tuple(observable)  # Python will die silently here

没有回溯,也没有迹象表明有任何问题。这使得已经很难调试的并发响应式代码更难调试——我花了 2 个小时才最终找到这个。


仔细观察,迭代 anObservable似乎会创建新的 observables,尽管我不知道从哪里可以观察到 observable 没有__iter__方法。

>>> for i, x in enumerate(observable):
>>>     print x
>>>     if i > 100:  # To prevent Python from crashing
>>>         break

<rx.anonymousobservable.AnonymousObservable object at 0x03111710>
<rx.anonymousobservable.AnonymousObservable object at 0x03111850>
<rx.anonymousobservable.AnonymousObservable object at 0x03111990>
<rx.anonymousobservable.AnonymousObservable object at 0x03111AD0>
<rx.anonymousobservable.AnonymousObservable object at 0x03111C10>
<rx.anonymousobservable.AnonymousObservable object at 0x03111D50>
<rx.anonymousobservable.AnonymousObservable object at 0x03111E90>
etc...

这是一个错误,还是一个功能?Observables是否可以迭代?

4

2 回答 2

1

我遇到了同样的问题,实际上我不小心将一个可观察对象变成了一个列表,这让我的电脑崩溃了,这有点好笑。

我不是专家,一周前我已经陷入困境,但这似乎是一个功能。默认情况下,可观察对象是非阻塞的,因此如果没有任何内容,它只会返回一个空的可观察对象。这就像一个使用 O_NONBLOCK 标志打开的文件:读取调用立即返回一个空字符串。

如果要将其用作阻塞迭代器,请使用to_blocking(). 然后,您可以执行以下操作:

from rx import Observable
o = Observable.from_([1, 2, 3, 4])
i = iter(o.to_blocking())
list(i)

它会完美地工作。

编辑:我刚刚发现为什么会这样。python的迭代器协议的方式和Observable上的方法之一,方法之间存在冲突next()。文档说:

next() — 返回一个迭代器,它会阻塞直到 Observable 发出另一个项目,然后返回该项目。

在 python 领域,next()预计将返回可迭代的下一项。因此,您将获得无限的可观察对象,每个都承诺在未来某个日期返回一个项目。

于 2016-06-07T07:15:56.370 回答
0

Observables 是可迭代的。这种行为实际上记录在这里

可观察的序列可以变成一个迭代器,这样你就可以使用生成器表达式,或者迭代它们(使用排队和阻塞)。

xs = Observable.from_([1,2,3,4,5,6])
ys = xs.to_blocking()
zs = (x*x for x in ys if x > 3)
for x in zs:
    print(x)
于 2017-01-14T14:53:19.040 回答