25 April 2006 15 comments Python
Casting is when you convert a variable value from one type to another. This is, in Python, done with functions such as
str(). A very common pattern is that you convert a number, currently as a string into a proper number.
Let me exemplify:
>>> x = '100' >>> y = '-90' >>> print x + y 100-90 >>> print int(x) + int(y) 10
That was the
int() function. There's also another very common one which is
float() which does basically the same thing:
>>> print float(x) + float(y) 10.0
Today I had to fix a bug might come as a surprise. Allow me to demonstrate:
>>> x = '100.0' >>> print float(x) 100.0 >>> print int(float(x)) 100 >>> print int(x) Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: invalid literal for int(): 100.0
As you can see, the
int() function can convert floating point numbers to integers just fine but it can't do that and decode it from a string in one statement. A flaw in the design? No, I don't think so. It's just another design decision that you just have to learn. But, is it to explicit? Would it be that bad if the
int() function could do both actions in one builtin sweep?
The bug I found was related to a human height input validator that looked something like this:
def validHeight(cm): try: cm = int(cm) return 100 <= cm <= 250 except ValueError: return False >>> validHeight(190) True >>> validHeight('190') True >>> validHeight('') False >>> validHeight('190.0') False # WHAT?!
You see, our system saves all values like this in the database as REAL (floating point decimal values) and when you return to the Height form it prints "190.0" as the default prefilled value in the input box. In the database it's a valid and correct value. The
validHeight() function had to be rewritten to this:
def validHeight(cm): try: cm = float(cm) return 100 <= cm <= 250 except ValueError: return False >>> validHeight(190) True >>> validHeight('190') True >>> validHeight('') False >>> validHeight('190.0') True
Geez! What a long boring story this became. Just remember,
float() is sometimes better than
int(). In some cases you might have to use both.