Python - 带有生成器的null对象模式

时间:2015-03-17 16:18:22

标签: python-2.7 generator

显然Pythonic返回的值可以被视为成功返回类型的'False'版本,这样if MyIterableObject: do_things()是一种处理输出的简单方法,无论它是否实际存在。< / p>

对于生成器,bool(MyGenerator)始终为True,即使它的len为0或同样为空。所以虽然我可以写下类似的东西:

result = list(get_generator(*my_variables))
if result:
    do_stuff(result)

似乎它首先打败了拥有发电机的好处。

也许我只是缺少一种语言特性,但是什么是pythonic语言结构,用于明确指出不使用空生成器完成工作?

要明确的是,我希望能够让用户了解脚本实际执行的工作量(如果有的话) - 上下文代码段如下:

# Python 2.7
templates = files_from_folder(path_to_folder)
result = list(get_same_sections(templates)) # returns generator
if not result:
    msg("No data to sync.")
    sys.exit()

for data in result:
    for i, tpl in zip(data, templates):
        tpl['sections'][i]['uuid'] = data[-1]

msg("{} sections found to sync up.".format(len(result)))

它有效,但我认为最终将生成器更改为列表只是为了查看是否有任何工作要做,所以我认为有更好的方法,是吗?

编辑:我觉得生成器不应该以这种方式使用,但我会添加一个例子来展示我的推理。

Python中有一个半流行的“辅助函数”,当你需要遍历嵌套dict或者你有什么的结构时,你会立刻看到它。通常称为getnodegetn,每当我看到它时,它都会显示如下:

def get_node(seq, path):
    for p in path:
        if p in seq:
            seq = seq[p]
        else:
            return ()
    return seq

因此,通过这种方式,您可以更轻松地处理嵌套结构中复杂数据路径的结果,而无需在实际处理时始终检查Nonetry/except用'特殊的东西'。

mydata = get_node(my_container, ('path', 2, 'some', 'data'))
if mydata:  # could also be "for x in mydata", etc
    do_work(mydata)
else:
    something_else()

看起来不像这种语法会(也可能)存在于生成器中,而不像已经建议的那样编写以这种方式处理生成器的类。

1 个答案:

答案 0 :(得分:0)

在您用尽迭代之前,生成器没有长度。

得到它是否有任何东西的唯一方法就是耗尽它

items = list(myGenerator)

if items:
    # do something

除非你写了一个属性非零的类,它在内部查看你的迭代列表

class MyGenerator(object):

    def __init__(self, items):
        self.items = items

    def __iter__(self):
        for i in self.items:
            yield i

    def __nonzero__(self):
        return bool(self.items)

>>> bool(MyGenerator([]))
False
>>> bool(MyGenerator([1]))
True
>>>