Python Core Data Types & Type Checking
Every value in Python has a type that determines what it can do. Python is dynamically typed Runtime: it works out a value’s type automatically when the code runs, and a variable can be reassigned to a value of a different type at any time.
Python is also strongly typed. It will not silently convert between unrelated types, so '5' + 5 is an error rather than 10 or '55'.
At a Glance
Section titled “At a Glance”| Task | Tool | Example |
|---|---|---|
| Find a value’s exact type | type(x) | type('hi') gives <class 'str'> |
| Check a value against a type | isinstance(x, T) | isinstance(5, int) gives True |
| Check against several types | isinstance(x, (A, B)) | isinstance(5, (int, float)) gives True |
| Convert between types | int(), float(), str(), bool() | int('42') gives 42 |
Dynamic Typing
Section titled “Dynamic Typing”A variable is just a name attached to a value. The type belongs to the value, not the name, so the name can be reattached to a value of any type.
age = 25 # intage = 'Twenty-five' # Now a str, which is perfectly legalCore Data Types
Section titled “Core Data Types”| Type | Name | Example | Notes |
|---|---|---|---|
int | Integer | 42, -7, 1_000_000 | Whole numbers with unlimited size. Underscores are allowed for readability. |
float | Float | 4.5, -0.01, 1e6 | Numbers with a decimal point. Stored as approximations. |
str | String | 'hello', "hello" | Text in single or double quotes. Immutable. |
bool | Boolean | True, False | Logical values. A subclass of int. |
NoneType | None | None | Represents “no value”. There is only one None. |
my_integer = 10 # <class 'int'>my_float = 4.50 # <class 'float'>my_string = 'hello' # <class 'str'>my_boolean = True # <class 'bool'>my_none = None # <class 'NoneType'>Numeric Behavior Worth Knowing
Section titled “Numeric Behavior Worth Knowing”print(10 / 2) # 5.0, the / operator always returns a floatprint(10 // 3) # 3, floor division returns an int for int operandsprint(2 ** 100) # 1267650600228229401496703205376, ints never overflowprint(1 + 2.0) # 3.0, int and float mix, and the result is a floatprint(0.1 + 0.2) # 0.30000000000000004, floats are approximationsCollection Types
Section titled “Collection Types”Collections hold multiple values. They are covered in their own guides, so this is just a preview.
| Type | Example | Mutable | Ordered |
|---|---|---|---|
list | [1, 2, 3] | Yes | Yes |
tuple | (1, 2, 3) | No | Yes |
dict | {'a': 1} | Yes | Yes (insertion order) |
set | {1, 2, 3} | Yes | No |
Mixing Types
Section titled “Mixing Types”Python promotes numbers automatically (int with float gives float), but it refuses to combine unrelated types.
print('5' * 3) # '555', repeating a string is allowedprint('5' + 5) # TypeError: can only concatenate str (not "int") to strprint(5 + '5') # TypeError: unsupported operand type(s) for +: 'int' and 'str'print('10' / 2) # TypeError: unsupported operand type(s) for /: 'str' and 'int'Type Conversion
Section titled “Type Conversion”Convert a value explicitly by calling the target type as a function.
| Call | Result | Notes |
|---|---|---|
int('42') | 42 | The string must look like a whole number |
int(3.9) | 3 | Truncates toward zero, it does not round |
float('4.5') | 4.5 | Accepts integer or decimal text |
str(10) | '10' | Works on almost any value |
bool('False') | True | Any non-empty string is truthy |
int('3.5') | ValueError | Convert through float first: int(float('3.5')) |
int('abc') | ValueError | Not a valid number |
Checking Types
Section titled “Checking Types”type()
Section titled “type()”type(value) returns the exact class of a value.
developer = 'Devin'
print(type(developer)) # <class 'str'>print(type(developer).__name__) # str, handy for readable messagesprint(type(developer) is str) # Trueisinstance()
Section titled “isinstance()”isinstance(value, type_or_tuple) returns True if the value matches the type, or any type in a tuple.
account_balance = '12'
print(isinstance(account_balance, int)) # Falseprint(isinstance(account_balance, (int, float))) # False, it is a stringprint(isinstance(account_balance, str)) # Truetype() vs. isinstance()
Section titled “type() vs. isinstance()”type(x) is T | isinstance(x, T) | |
|---|---|---|
| Matches | The exact type only | The type and any type built on top of it |
| Multiple types | Needs or | Accepts a tuple |
| Typical use | Strict checks, debugging | General validation |
The difference shows up with booleans, which are built on top of integers:
print(type(True) is int) # False, the exact type is boolprint(isinstance(True, int)) # True, bool is built on top of intThe Boolean Trap
Section titled “The Boolean Trap”In Python, bool is built on top of int. As a result, True and False pass an integer check.
print(isinstance(True, int)) # True, a surpriseprint(True + True) # 2, booleans behave like 1 and 0print(type(True) is int) # False, the exact type is boolThis causes real bugs. Code expecting a quantity will happily accept True as 1. To reject booleans when you need an integer, use either approach:
value = True
# Option 1: allow int, but explicitly exclude boolprint(isinstance(value, int) and not isinstance(value, bool)) # False
# Option 2: exact type matchprint(type(value) is int) # FalseValidating Before You Operate
Section titled “Validating Before You Operate”-
Identify the type. Use
type()to discover what a variable currently holds, especially while debugging. -
Validate the input. Run
isinstance()to confirm the value is safe to process. -
Filter out booleans if needed. Remember that
TrueandFalsepass integer and numeric checks. -
Execute safely. Run math or text operations only after the value has passed validation.
account_balance = '12'
if isinstance(account_balance, (int, float)) and not isinstance(account_balance, bool): print(account_balance / 2)else: print('Error: Operation rejected. Balance is not numeric.') # RunsCommon Mistakes
Section titled “Common Mistakes”| isinstance(x, int) to reject booleans | True and False pass | Use type(x) is int |