Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python negate boolean function

A python boolean function can easily be negated with lambda functions, but it's a bit verbose and hard to read for something so basic, for example:

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

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

I'm wondering if there is a function to do this in the standard library, which might look like:

odds_under_50 = filter(negate(is_even), range(50))
like image 594
Vaelus Avatar asked Mar 02 '17 17:03

Vaelus


People also ask

How do you negate a Boolean expression?

Negate a Boolean expression. To negate a Boolean expression you simply have to apply the DeMorgan theorem recursively: (1) The negation of a sum is the product of the negated variables. (2) The negation of a product is the sum of the negated variables.

How do you do negation in Python?

The negation operator in Python is not . Therefore just replace your ! with not .

What operator is used to negate or take the opposite of a Boolean value?

The logical NOT ( ! ) operator (logical complement, negation) takes truth to falsity and vice versa. It is typically used with boolean (logical) values. When used with non-Boolean values, it returns false if its single operand can be converted to true ; otherwise, returns true .


4 Answers

As far as I know there is no builtin function for that, or a popular library that does that.

Nevertheless, you can easily write one yourself:

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

You can then use:

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

The negate function works for an arbitrary amount of parameters of the given function: if you would have defined is_dividable(x,n=2). Then negate(is_dividable) is a function with two arguments (one optional) that would also accept these parameters.

like image 156
Willem Van Onsem Avatar answered Sep 24 '22 01:09

Willem Van Onsem


With funcy's or toolz's compose function you can negate the function like that:

import operator

import funcy

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

If you want to make it more readable:

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))

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


In case of filter you can use ifilterfalse from itertools.

like image 34
lukeg Avatar answered Sep 22 '22 01:09

lukeg


You can create a decorator:

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)

This decorator can also be used with @negate.

@negate
def is_odd(x):
    return x % 2 == 0
like image 30
lelabo_m Avatar answered Sep 24 '22 01:09

lelabo_m