如何解决如何创建一个生成器,以生成特定的,不相关的惰性计算表达式
在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 举报,一经查实,本站将立刻删除。