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 oring 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 oring 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)