Is there an implication logical operator in python?
Solution 1
p => q
is the same as not(p) or q
, so you could try that!
Solution 2
Just because it's funny: x => y could be bool(x) <= bool(y)
in python.
Solution 3
There is a converse implication operator:
if y ** x:
do_sth()
This reads: If y is implied by x.
Credits to https://github.com/cosmologicon/pywat
Solution 4
Your question asks if there is a single logical operator for this in Python, the simple answer is no: The docs list boolean operations, and Python simply doesn't have anything like that.
Obviously, as Juampi's answer points out, there are logically equivalent operations that are a little shorter, but no single operators as you asked.
Solution 5
Additional details based on what I have found here and there as I was looking for an implication operator : you can use a clever hack to define your own operators. Here is a running example annotated with sources leading me to this result.
#!/usr/bin/python
# From http://code.activestate.com/recipes/384122/ (via http://stackoverflow.com/questions/932328/python-defining-my-own-operators)
class Infix:
def __init__(self, function):
self.function = function
def __ror__(self, other):
return Infix(lambda x, self=self, other=other: self.function(other, x))
def __rlshift__(self, other):
return Infix(lambda x, self=self, other=other: self.function(other, x))
def __or__(self, other):
return self.function(other)
def __rshift__(self, other):
return self.function(other)
def __call__(self, value1, value2):
return self.function(value1, value2)
from itertools import product
booleans = [False,True]
# http://stackoverflow.com/questions/16405892/is-there-an-implication-logical-operator-in-python
# http://jacob.jkrall.net/lost-operator/
operators=[
(Infix(lambda p,q: False), "F"),
(Infix(lambda p,q: True), "T"),
(Infix(lambda p,q: p and q), "&"),
(Infix(lambda p,q: p or q) , "V"),
(Infix(lambda p,q: p != q) , "^"),
(Infix(lambda p,q: ((not p) or not q)), "nad"),
(Infix(lambda p,q: ((not p) and not q)), "nor"),
(Infix(lambda p,q: ((not p) or q)), "=>"),
]
for op,sym in operators:
print "\nTruth tables for %s" % sym
print "\np\tq\tp %s q\tq %s p" % (sym,sym)
for p,q in product(booleans,repeat=2):
print "%d\t%d\t%d\t%d" % (p,q,p |op| q,q |op| p)
print "\np\tq\tr\tp %s q\tq %s r\t(p %s q) %s r\tp %s (q %s r)\tp %s q %s r" % (sym,sym,sym,sym,sym,sym,sym,sym)
for p,q,r in product(booleans,repeat=3):
print "%d\t%d\t%d\t%d\t%d\t%d\t\t%d\t\t%d" % (p,q,r,p |op| q,q |op| r, (p |op| q) |op| r, p |op| (q |op| r), p |op| q |op| r)
assert( (p |op| q) |op| r == p |op| q |op| r)
Comments
-
running.t almost 2 years
I would like to write a statement in python with logical implication. Something like:
if x => y: do_sth()
Of course, I know I could use:
if (x and y) or not x: do_sth()
But is there a logical operator for this in python?
-
running.t almost 11 yearsAnd that is simplier than (x and y) or not x. Thanks
-
user2246674 almost 11 yearsThe TTL agrees - but it's not necessarily so easy to see in code, although simpler than the original. A function - i.e.
implies(x, y)
- might help with transferring the idea more, if such a construct occurs often enough to warrant a name. -
Gareth Latty almost 11 years@user2246674 Agreed, I would recommend making this a function for clarity.
-
Mark Dickinson over 8 yearsAnd this is (finally) conclusive proof that
True
should be-1
andFalse
should be0
for booleans! (Instead of the current Python convention ofTrue == 1
.) Because then we'd havex => y
matchingy <= x
(which looks like a right-to-left implication) for booleans. -
running.t over 8 yearsYes. This is exactly what I was looking for. And it looks like this converse implication is undocumented, so @Latty 's answer basically is incorrect.
-
running.t over 8 years
-
Gareth Latty over 8 years@running.t This is something that happens to have the same effect as
x => y
, but is not an operator for that purpose. This is the power operator, and is not a logical operator, but a numerical one. It does not returnTrue
orFalse
, but a number. This is slower, and could potentially introduce bugs, not to mention being incredibly unclear and hard to read. I would highly recommend against ever doing this, and instead would usenot(p) or q
as per Juampi's answer. -
Gareth Latty over 8 years@running.t It is not in the docs because that answer is wrong - there is no such operator, instead, it is an abuse of another operator that happens to produce the same result. The end result of using that would be horribly unlcear, inefficient code which may introduce bugs.
-
Sylvain over 5 yearsen.wikipedia.org/wiki/Material_nonimplication also equivalent to
p and not(q)
-
Alexey almost 5 yearsI would have liked to have a bitwise version of this too.
-
Alexey almost 5 years@GarethLatty, a "purpose" of an operator only makes sense for a particular class/type (operators can and should be overloaded). Note by the way that the
+
operator is arguably not for the purpose of doing"Hell" + "o"
. Regarding the power operator**
for Booleans that is not properly overloaded and does not returnTrue
/False
, IMO this is a Python's bug or misfeature. IfA
andB
are two sets, thenA^B
(A
to the powerB
) is the standard notation for the set of functionsB -> A
. Under Curry–Howard correspondence, a functionB -> A
represents a proof ofB => A
. -
Gareth Latty almost 5 years@Alexey "Operators can and should be overloaded." is a strong statement. Operators are hard to search for and rely on the user's perception of the operator, so should generally be avoided in favour of functions where the meaning isn't very clear to most people. The vast majority of people reading that code will find it less clear than the alternative, and—regardless of it being a bug or intentionally not done—it isn't implemented efficiently. You can argue that shouldn't be the case, but it definitely is at the moment. Given that, I'd highly recommend against it.
-
Alexey almost 5 years@GarethLatty, ok, maybe operators should not always be overloaded, maybe even
"Hell" + "o"
is a design mistake. However, interpretinga^b
asb => a
for logical values seems fairly reasonable to me. About the**
for Booleans supposedly being slower, i could not confirm it. I've just tried to compareTrue or not True
withTrue**True
, andTrue**True
was almost twise faster (measured with%timeit
in IPython, Python 3.7.3). -
Gareth Latty almost 5 years@Alexey While there are certainly arguments against
+
for string concat,+
meaning an addition makes a lot of sense to most people instinctively. Maybe to those with the right background^
is clear, but I would argue that is very niche at best. If your project is aimed at the right crowd, maybe it's more reasonable. Slower, I accept may well not be true (particularly any more), that was a long time ago. I would argue that the micro-optimisation here is the least important aspect, and readability should trump that unless it's a specific bottleneck you have identified. -
user2846495 about 3 yearsOne potential gotcha if you make an
implies(x, y)
function: because of Python's strict evaluation, the consequenty
will always be evaluated (the operation will not be short-circuiting). You would think this would be obvious, but I just spent 30 minutes scratching my head over this problem.