Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using IF, AND, OR together with EQUAL operand together in Python [duplicate]

I'm trying to create a function where the given value (passed as a string) is checked to see if the number of digits is either 4 or 6, and that it is a number.

My first impulse was to go with this code:

def number(x):
    if (len(x) == (4 or 6)) and x.isdigit():
        print "True"
    else:
        print "False"

This code above only passes the first test below...I don't understand why it passes this but none of the other tests:

number("1234")

Only when I separate out the len() functions will it work properly.

def number(x):
    if (len(x) == 4 or len(x) == 6) and x.isdigit():
        print "True"
    else:
        print "False"


## Checks
number("1234")
number("123456")
number("abcd")
number("abcdef")
number("1")
number("a")

The above code passes all tests.

So my questions are:

  1. What's going on here?
  2. Any way to write cleaner code for this?

Thank for the help!

** Not a duplicate question because although this question has the same underlying concepts regarding boolean operators, the problem itself is different due to the usage of len(), isdigit(), and the additional question of how best to improve it (someone commented the usage of return). Definitely adds another perspective to the other question though.

like image 872
jhub1 Avatar asked Jul 20 '16 17:07

jhub1


2 Answers

It helps to examine the logic of this line:

if (len(x) == (4 or 6)):

The (4 or 6) clause contains a logical or short circuit. The value 4 is true, so it is evaluated and returned to the == relational comparison.

The way that or works is that its lefthand side is evaluated for Boolean truth, and its value is returned if true. If the lefthand side is not Boolean true, then the righthand side is evaluated and its value is returned.

Because the lefthand side of the 4 or ... is true in a Boolean sense, the righthand side is never evaluated. Python doesn't even look past 4 or. If the left-hand value were a false value (such as 0), then the right hand side of the or would be evaluated.

To see this in action, try print 4 or 6. The output will be 4.

So since the 4 is a hard-coded true value, your comparison is semantically the same as if (len(x) == 4) -- that is, since 4 is true, 6 is never evaluated.

What I suppose you really want to know is if len(x) is either 4 or 6. You could put that to code in a couple of ways:

if(len(x) == 4 or len(x) == 6 ...

if(len(x) in (4,6) ...
like image 169
DavidO Avatar answered Nov 15 '22 22:11

DavidO


You can use the in operator like so:

def number(x):
    if len(x) in (4, 6) and x.isdigit():
    print "True"
else:
    print "False"

where in checks for containment in a given container. Note that 4 or 6 on their own evaluate to something undesirable, which is why your first code segment fails. You can check it out on the python shell:

>>> 4 or 6
4
like image 27
ifma Avatar answered Nov 15 '22 22:11

ifma