【问题标题】:Python negate boolean functionPython 否定布尔函数
【发布时间】:2017-07-22 13:23:27
【问题描述】:

python 布尔函数可以很容易地用 lambda 函数求反,但是对于如此基本的东西来说它有点冗长且难以阅读,例如:

def is_even(n):
    return n % 2 == 0

odds_under_50 = filter(lambda x: not is_even(x), range(50))

我想知道标准库中是否有执行此操作的函数,可能如下所示:

odds_under_50 = filter(negate(is_even), range(50))

【问题讨论】:

  • 据我所知,没有 builtin 函数,但您可以轻松地为此定义自己的高阶函数...
  • 据我所知;在这种情况下,我只会使用列表理解:[xi for xi in range(50) if not is_even(xi)]
  • @Cleb: 不是 Python-3.x 中的 filter 和这个列表理解是不等价的,因为 filter 是懒惰的:你可以 filter 一个无限的生成器,而你不能这样做列表理解。
  • @WillemVanOnsem:在实际中会有什么不同?在 cmets 中讨论可能会很棘手,但我目前看不出有什么区别。当我阅读documentation 时,我也没有发现区别(除了列表与迭代器)。
  • 如果你 import itertools 然后执行 [xi for xi in itertools.repeat(1) if not is_even(xi)] 这将耗尽内存。 filter 将延迟评估,因此根本不消耗 CPU/内存。

标签: python standard-library


【解决方案1】:

据我所知,没有 builtin 函数可以做到这一点,也没有流行的库可以做到这一点。

不过,您可以自己轻松编写一个:

from functools import wraps

def negate(f):
    @wraps(f)
    def g(*args,**kwargs):
        return not f(*args,**kwargs)
    g.__name__ = f'negate({f.__name__})'
    return g

然后您可以使用:

odds_under_50 = filter(<b>negate(is_even)</b>, range(50))

negate 函数适用于给定函数的任意数量的参数:如果您定义了is_dividable(x,n=2)。那么negate(is_dividable) 是一个带有两个参数(一个可选)的函数,它们也可以接受这些参数。

【讨论】:

  • 这里值得注意的是,否定函数将与原始函数具有相同的文档字符串和名称,这可能不是一个好主意。
  • 这里@wraps有什么用?
  • @cs95:保证参数数据与f一致,否则就是*args**kwargs
  • @cs95: 或许我们可以使用g.__name__ = f'negate({f.__name__})',从而保留参数数据将函数名称更改为negate(f),这样会更好如果f 有参数ab,我们会得到帮助negate(f)(a, b)
【解决方案2】:

如果是filter,您可以使用来自itertoolsifilterfalse

【讨论】:

【解决方案3】:

你可以创建一个装饰器:

def negate(function):
    def new_function(*args, **kwargs):
       return not function(*args, **kwargs)
return new_function


def is_even(x):
    return x % 2 == 0

print is_even(1)
print is_even(2)

is_odd = negate(is_even)
print is_odd(1)
print is_odd(2)

这个装饰器也可以和@negate一起使用。

@negate
def is_odd(x):
    return x % 2 == 0

【讨论】:

    【解决方案4】:

    使用 funcy's 或 toolz's compose 函数,您可以像这样否定函数:

    import operator
    
    import funcy
    
    is_odd = funcy.compose(operator.not_, is_even)
    

    如果你想让它更具可读性:

    def negate(func):
        return funcy.compose(operator.not_, func)
    
    is_odd = negate(is_even)
    
    # or without creating the function directly
    print(negate(is_even)(5))
    

    funcy library has a lot of other useful functions for functional programming

    【讨论】:

      猜你喜欢
      • 2019-01-19
      • 2021-12-06
      • 2015-09-05
      • 2013-05-06
      • 2018-10-04
      • 2021-11-28
      • 1970-01-01
      • 1970-01-01
      • 2011-10-17
      相关资源
      最近更新 更多