-2

I can't seem to wrap my head around the output of this function:

def is_integer(num1, num2):
        if isinstance(num1 and num2, int):
            return 'Yes'
        else:
            return 'No'

print(is_integer(1.4, 2))

This will output 'Yes', but it shouldn't as 1.4 and 2 are not both integers. Any help?

PYB
  • 503
  • 6
  • 20
  • `num1 and num2` means `num1` if it's falsey (`False`, `None`, zero, or empty), otherwise `num2`. That probably isn't what you wanted to check. – abarnert Jun 27 '18 at 04:16

2 Answers2

2

The way the and operator works in Python is:

The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.

In Python, None, False, numeric zeros, and empty collections are false; almost everything else is true.1

So, 1.4 and 2 means 2, because 1.4 is not zero.

So, isinstance(1.4 and 2, int) means isinstance(2, int).

And 2 is an int.


What you probably wanted here is:

if isinstance(num1, int) and isinstance(num2, int):

… or:

if all(isinstance(num, int) for num in (num1, num2)):

1. To avoid confusion between the specific True and False values and the more abstract idea of true and false values, most Python developers refer to None/False/zero/empty as "falsey" rather than "false", and everything else as "truthy" rather than "true". But the documentation avoids this cutesiness, and I'm quoting from the docs here.

abarnert
  • 354,177
  • 51
  • 601
  • 671
0
isinstance(num1 and num2, int)

Is the same as

t1 = num1 and num2
if isinstance(t1, int)

The result of an and between two numbers returns the first Falsy value if there are any, else returns the last value in the expression.

Some examples:

In [24]: 1.4 and 2
Out[24]: 2

In [25]: 1.4 and 2 and 3
Out[25]: 3

In [26]: 1.4 and 0 and 2
Out[26]: 0

For more information, see Strange use of "and" / "or" operator.


If you want to test both, you have to do them separately:

def is_integer(num1, num2):
    if isinstance(num1, int) and isinstance(num2, int):
        return 'Yes'        
    return 'No'

Which is a more wieldy way of writing

def is_integer(num1, num2):
    if all(isinstance(n, int) for n in (num1, num2)):
        return 'Yes'        
    return 'No'

...with the all function which generalises to more than 2 arguments.

Better still, have your function accept a variable number of arguments:

def is_integer(*args):
    if all(isinstance(n, int) for n in args):
        return 'Yes'
    return 'No'

Better still, return a boolean result:

def is_integer(*args):
    return all(isinstance(n, int) for n in args)
cs95
  • 379,657
  • 97
  • 704
  • 746
  • 2
    "As long as both numbers != 0, t1 == True" - no, `and` in Python returns one of its arguments. If neither of its arguments is a boolean, the result won't be a boolean. – user2357112 Jun 27 '18 at 04:20
  • @user2357112 ugh, sorry. Fixed. – cs95 Jun 27 '18 at 04:22