3

是否有内省生成器对象的技术(例如用于单元测试中的断言)?

更具体地说,我有一个数据处理管道,由一系列小函数组成,这些函数通常应用于列表推导或生成器表达式中的值,如下所示:

生成一些随机数据:

>>> raw_data = ["${}".format(RND.randint(10, 100)) for c in range(10)]

>>> # a function that does some sort of of transform
>>> fnx = lambda q: float(q.replace('$', ''))

>>> d1 = [fnx(itm) for itm in raw_data]

在下一步中,将在d1的项目上应用另一个变换函数,依此类推。

在上面的例子中,例如,关于prices_clean的长度,或者关于它的值的最小值/最大值等的断言是我的单元测试套件的核心:

>>> assert len(d1) == 10

鉴于我只是要遍历这些中间结果,我实际上并不需要一个列表,一个生成器对象就可以了,并且考虑到内存配置文件要低得多,这就是我使用的:

>>> d1 = (fnx(itm) for itm in raw_data)

当然,我在使用列表推导时所依赖的断言不适用于生成器对象:

>>> d1
  <generator object <genexpr> at 0x106da9230>

>>> assert len(d1) == 10
  Traceback (most recent call last):
  File "<pyshell#33>", line 1, in <module>
    assert len(d1) == 10
  TypeError: object of type 'generator' has no len()

如果我必须在生成器对象上调用list()只是为了断言,那么我的测试套件运行非常缓慢(不幸的实际结果是 debs 通常根本不运行它)。

我已经查看了生成器对象的属性,以了解我可以有效地自省的任何内容,但我没有看到如何以我在此处描述的方式经常使用它们。

4

2 回答 2

4

生成器对象的类型检查参考

import types
self.assertIsInstance(_result_generator, types.GeneratorType)
于 2017-07-10T04:51:05.273 回答
2

正如@thg435 评论的那样,不消耗它,你不知道生成器的长度。

通常我会执行以下操作之一:

如果生成器产生少量元素:

assert len(list(d1)) == 10

或者

assert sum(1 for x in d1) == 10
于 2013-10-05T09:41:06.013 回答