微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何创建一个生成器,以生成特定的,不相关的惰性计算表达式

如何解决如何创建一个生成器,以生成特定的,不相关的惰性计算表达式

在Python中发现all()函数后发现此问题并没有像我期望的那样短路,因为您发送的列表内的表达式不是惰性计算的。所以:

all([
    prevIoUs_task is not None,self.task_type == prevIoUs_task.task_type,self.owner is None,prevIoUs_task.owner is None,self.is_sibling_of(prevIoUs_task)
    ])

例如,在此代码中,如果prevIoUs_task为None,则self.task_type == prevIoUs_task.task_type在尝试访问prevIoUs_task.task_type时仍会评估并抛出异常

尽管这样很容易解决(并且实际上短路并且很懒):

prevIoUs_task is not None and all([ 
    self.task_type == prevIoUs_task.task_type,self.is_sibling_of(prevIoUs_task)
    ])

实际上,核心问题在于列表表达式在创建时会急切地评估内部代码

因此解决方案是创建一个生成器,因此它实际上仅逐项评估项目。但是...生成器需要对某些东西的理解才能真正生成。或带有yield参数的函数

尽管我可以做这样的事情:

def __evaluate(self,prevIoUs_task):
    yield prevIoUs_task is not None
    yield self.task_type == prevIoUs_task.task_type
    yield self.owner is None
    yield prevIoUs_task.owner is None
    yield self.is_sibling_of(prevIoUs_task)

可读性受到损害,无法达到all的目的。

我在PEP上发现可以使用类似这样的东西:

(condition 
    for evaluation 
    in (
        prevIoUs_task is not None,self.is_sibling_of(prevIoUs_task)
    )
)

这也不起作用,因为第二个括号是集合文字,而不是生成器,它将像列表一样评估构造中集合的内容

另一种选择是从lambda列表中进行reduce参数,如下所示:

reduce(
    lambda actual,next_function: actual and next_function(),[
        lambda: prevIoUs_task is not None
        lambda: self.task_type == prevIoUs_task.task_type
        lambda: self.owner is None
        lambda: prevIoUs_task.owner is None
        lambda: self.is_sibling_of(prevIoUs_task)
    ]
)

太冗长,尽管仍然很可读

那么...我缺少什么吗?有什么方法可以简洁地做到这一点?仅进行懒惰状态评估似乎太困难了

如果只有这些可能性,我可以考虑做一个utils库D:

编辑:忘记了我没有明确提出的显而易见的解决方案,在这里您可以只链接and,但是事实是这样做违背了all的目的。而且我认为,从长远来看,知道如何使无关值的生成器有用,而不仅仅是发送and垃圾邮件,这会妨碍可读性并迫使您以巨大的表达式“硬编码”条件

    (prevIoUs_task is not None
and self.task_type == prevIoUs_task.task_type
and self.owner is None
and prevIoUs_task.owner is None
and self.is_sibling_of(prevIoUs_task)
    )

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。