Type Casting in Python — Convert Between Data Types Safely
Advertisement
Introduction
Why This Matters
Type casting — converting values from one data type to another — is one of the most common operations in Python. When you read user input, all values come in as strings and must be converted. When working with APIs, JSON values may need to be cast to match your data model. When processing CSV files, numeric columns arrive as strings that need to become integers or floats.
Understanding both implicit conversion (which Python does automatically) and explicit conversion (which you control) prevents TypeError and ValueError at runtime. Knowing the edge cases — what fails, what loses precision, and how to validate before casting — makes your code more robust.
This is also fundamental knowledge for data pipelines, form processing, and any code that handles user-supplied data.
Implicit Type Conversion
Python automatically converts types in some expressions to prevent data loss.
# int + float → float
result = 5 + 2.5
print(result) # 7.5
print(type(result)) # <class 'float'>
# int + complex → complex
z = 3 + (1 + 2j)
print(z) # (4+2j)
print(type(z)) # <class 'complex'>
# bool is a subtype of int
print(True + 1) # 2
print(False + 10) # 10
print(True * 5) # 5Explicit Type Conversion — int()
# String to int
print(int("42")) # 42
print(int(" 10 ")) # 10 (strips whitespace)
# Float to int (truncates, does not round)
print(int(3.9)) # 3
print(int(-3.9)) # -3
# Bool to int
print(int(True)) # 1
print(int(False)) # 0
# Different bases
print(int("0b1010", 2)) # 10 (binary)
print(int("FF", 16)) # 255 (hexadecimal)
print(int("777", 8)) # 511 (octal)
# Fails
try:
int("hello")
except ValueError as e:
print(e) # invalid literal for int() with base 10: 'hello'Explicit Type Conversion — float()
print(float(42)) # 42.0
print(float("3.14")) # 3.14
print(float("1e3")) # 1000.0
print(float(True)) # 1.0
print(float("inf")) # inf
print(float("-inf")) # -inf
# Fails
try:
float("abc")
except ValueError as e:
print(e) # could not convert string to float: 'abc'Explicit Type Conversion — str()
print(str(42)) # '42'
print(str(3.14)) # '3.14'
print(str(True)) # 'True'
print(str(None)) # 'None'
print(str([1, 2, 3])) # '[1, 2, 3]'
# For custom objects, define __str__
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"({self.x}, {self.y})"
print(str(Point(3, 4))) # (3, 4)Explicit Type Conversion — bool()
Falsy values: 0, 0.0, "", [], {}, set(), None, False
print(bool(0)) # False
print(bool(0.0)) # False
print(bool("")) # False
print(bool([])) # False
print(bool({})) # False
print(bool(None)) # False
print(bool(1)) # True
print(bool(-1)) # True
print(bool("0")) # True — non-empty string
print(bool([0])) # True — non-empty listConverting Between Collections
# list, tuple, set conversions
numbers = [1, 2, 3, 2, 1]
t = tuple(numbers) # (1, 2, 3, 2, 1)
s = set(numbers) # {1, 2, 3} — deduplicated
l = list(s) # [1, 2, 3] (order not guaranteed)
back = sorted(list(s)) # [1, 2, 3]
# String to list of chars
chars = list("hello") # ['h', 'e', 'l', 'l', 'o']
joined = "".join(chars) # 'hello'
# Range to list
nums = list(range(5)) # [0, 1, 2, 3, 4]
# Dict from pairs
pairs = [("a", 1), ("b", 2)]
d = dict(pairs) # {'a': 1, 'b': 2}Safe Conversion Patterns
def safe_int(value, default: int = 0) -> int:
try:
return int(value)
except (ValueError, TypeError):
return default
print(safe_int("42")) # 42
print(safe_int("hello")) # 0
print(safe_int(None)) # 0
print(safe_int("3.7")) # 0 — int() won't parse floats-as-strings
# Safe float-to-int
def to_int(value) -> int:
try:
return int(float(value)) # handles "3.7" → 3
except (ValueError, TypeError):
return 0
print(to_int("3.7")) # 3Common Mistakes
- Using
int("3.7")directly — raisesValueError; useint(float("3.7"))instead - Expecting
int()to round — it always truncates toward zero - Forgetting that
str(None)gives"None", not an empty string - Assuming
bool("False")isFalse— any non-empty string is truthy - Converting large float to int when precision matters — use
Decimalinstead
Best Practices
- Always wrap user input conversions in
try/exceptwith a meaningful error message - Use
isinstance(value, int)to check type before converting - Use
Decimalfor monetary values — float arithmetic has precision issues - Validate string format before converting with
str.isdigit()orstr.isnumeric() - Use
int(float(x))to safely convert "3.7"-style strings to integers
Key Takeaways
- Python's implicit conversion promotes types to prevent data loss (int → float, bool → int)
int()truncates floats — it does not round; useround()if rounding is neededint("3.7")raisesValueError— convert to float first:int(float("3.7"))bool()treats0,"",[],{},Noneas falsy; everything else is truthylist(),tuple(),set(),dict()convert between collection types- Always wrap type conversions on untrusted input in
try/except - Use
Decimalfor precise decimal arithmetic; float has IEEE 754 rounding issues
Advertisement