Is there an implication logical operator in python?

20,404

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)
Share:
20,404
running.t
Author by

running.t

Python/Big Data developer

Updated on July 09, 2022

Comments

  • running.t
    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
    running.t almost 11 years
    And that is simplier than (x and y) or not x. Thanks
  • user2246674
    user2246674 almost 11 years
    The 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
    Gareth Latty almost 11 years
    @user2246674 Agreed, I would recommend making this a function for clarity.
  • Mark Dickinson
    Mark Dickinson over 8 years
    And this is (finally) conclusive proof that True should be -1 and False should be 0 for booleans! (Instead of the current Python convention of True == 1.) Because then we'd have x => y matching y <= x (which looks like a right-to-left implication) for booleans.
  • running.t
    running.t over 8 years
    Yes. 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
    running.t over 8 years
    Please take a look at this answer. It looks like not everything can be found in docs.
  • Gareth Latty
    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 return True or False, 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 use not(p) or q as per Juampi's answer.
  • Gareth Latty
    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
    Sylvain over 5 years
    en.wikipedia.org/wiki/Material_nonimplication also equivalent to p and not(q)
  • Alexey
    Alexey almost 5 years
    I would have liked to have a bitwise version of this too.
  • Alexey
    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 return True/False, IMO this is a Python's bug or misfeature. If A and B are two sets, then A^B (A to the power B) is the standard notation for the set of functions B -> A. Under Curry–Howard correspondence, a function B -> A represents a proof of B => A.
  • Gareth Latty
    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
    Alexey almost 5 years
    @GarethLatty, ok, maybe operators should not always be overloaded, maybe even "Hell" + "o" is a design mistake. However, interpreting a^b as b => 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 compare True or not True with True**True, and True**True was almost twise faster (measured with %timeit in IPython, Python 3.7.3).
  • Gareth Latty
    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
    user2846495 about 3 years
    One potential gotcha if you make an implies(x, y) function: because of Python's strict evaluation, the consequent y 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.