These are not the same thing. Compare these two lines:
if type(x) == int or float:
if type(x) == int or type(x) == float:
And that's the difference.
The first one is checking type(x) == int
, and then taking the result and or
ing it with float
, so it's going to return True
if x
is an int
, and float
if it's anything else. Since both True
and float
are truthy values, the if
part will always happen, and the else
will never happen.
The second one is checking type(x) == int
, and type(x) == float
, and or
ing them together. So, it's going to return True
if x
is an int
or if x
is a float
, and False
if it's anything else.
You can simplify the code by using the in
operator:
if type(x) in (int, float)
But it's still not very good Python. If you really want to type-switch, you almost always want to do it with isinstance
rather than comparing the types:
if isinstance(x, (int, float)):
This means your code will work if it's passed, say, a subclass of int
. But it still won't work for, say, a wrapper around int
, or some custom-designed integral type, or even (in Python 2.x) a long
. So, a better version is:
if isinstance(x, numbers.Real)
This returns True for float
, int
, long
, and various other builtin types, and any subclasses of those types, and anything that registers itself with the numbers.Real
ABC.
But really, you usually don't want to type-switch at all. Python is designed around duck typing. What you care about here is that you can successfully pass it to abs
. Who cares what specific type it actually is, as long as you can do that? So:
try:
return abs(x)
except TypeError:
return "Not a number!"
Or, even better, instead of catching the exception and returning a string (which means that any caller is going to have to handle both numbers and strings, and so on up the chain), just let the exception propagate:
return abs(x)