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))
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.
The negation operator in Python is not . Therefore just replace your ! with not .
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 .
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.
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
.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With