当前位置:  开发笔记 > 编程语言 > 正文

惯用Python has_one

如何解决《惯用Pythonhas_one》经验,为你挑选了1个好方法。

我刚刚发明了一个愚蠢的小助手功能:

def has_one(seq, predicate=bool):
    """Return whether there is exactly one item in `seq` that matches
    `predicate`, with a minimum of evaluation (short-circuit).
    """
    iterator = (item for item in seq if predicate(item))
    try:
        iterator.next()
    except StopIteration: # No items match predicate.
        return False
    try:
        iterator.next()
    except StopIteration: # Exactly one item matches predicate.
        return True
    return False # More than one item matches the predicate.

因为我能想到的最可读/惯用的内联事物是:

[predicate(item) for item in seq].count(True) == 1

...在我的情况下这很好,因为我知道seq很小,但它只是感觉很奇怪.有没有我在这里忘记的成语,这使我不得不打破这个助手?

澄清

回顾它,这是一个令人讨厌的问题,虽然我们得到了一些很好的答案!我正在寻找:

一个明显的,可读的内联习语或stdlib函数,在这种情况下,急切的评估是可以接受的.

一个更明显和可读的辅助函数 - 因为它打破了整个其他函数,只有最小的评估量似乎是可以接受的.

@ Stephan202想出了辅助功能和一个很酷的成语@马丁诉Löwis与谓词返回一个布尔值的假设下,更简单的在线成语上来.感谢@大家的帮助!



1> Stephan202..:

如何any在迭代器上调用两次(Python 2.x和3.x兼容)?

>>> def has_one(seq, predicate=bool):
...     seq = (predicate(e) for e in seq)
...     return any(seq) and not any(seq)
... 
>>> has_one([])
False
>>> has_one([1])
True
>>> has_one([0])
False
>>> has_one([1, 2])
False

any最多需要一个True从迭代器求值的元素.如果第一次成功并且第二次失败,则只有一个元素与谓词匹配.

编辑:我看到Robert Rossney提出了一个通用版本,它检查n个元素是否与谓词匹配.让我加入乐趣,使用all:

>>> def has_n(seq, n, predicate=bool):
...     seq = (predicate(e) for e in seq)
...     return all(any(seq) for _ in range(n)) and not any(seq)
... 
>>> has_n(range(0), 3)
False
>>> has_n(range(3), 3)
False
>>> has_n(range(4), 3)
True
>>> has_n(range(5), 3)
False

推荐阅读
帆侮听我悄悄说星星
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有