Skip to content

Basic Data Types

Every value in Python has a type, which determines what operations it supports and how it behaves — Python figures this out from the value itself, since you never declare a type explicitly. A basic (or "scalar") data type holds a single, indivisible value, as opposed to a collection, which groups many values together. The basic types are also all immutable: once created, the value itself can never be changed in place — only replaced with a different value.

Type Example Mutable (changeable after creation) Use it for
int 5 No
  • Counts — how many of something there are, like items in a list
  • Indexes — the position of an item in a sequence, like species[2]
  • IDs — a unique whole-number identifier, like a user or record ID
float 4.5 No
  • Measurements, ratios — anything with a decimal
  • Binary rounding errors mean 0.1 + 0.2 != 0.3
str "ball python" No
  • Text — names, labels, messages
  • Ordered and indexable like a list, but immutable — .upper(), .replace(), etc. return a new string
bool True No
  • Flags, yes/no switches, comparison results (length > 3)
  • Secretly a subclass of intTrue + True == 2
None None No
  • Marking "no value yet" — a default placeholder, or what a function returns if it falls through without a return
  • Compare with is None, not == None

Integers

An integer (int) is a whole number — positive, negative, or zero — with no decimal point.

length = 5

print(length)

Arithmetic

length + 3     # 8
length - 2     # 3
length * 2     # 10
length / 2     # 2.5  (/ always returns a float)
length // 2    # 2    (floor division — drops the remainder)
length % 2     # 1    (modulo — the remainder)
length ** 2    # 25   (exponent)

The standard math operators work as expected, with two that surprise beginners: / (true division) always returns a float, even when the numbers divide evenly — use // (floor division) if you want an int result.

length = 5

print(length + 3)
print(length - 2)
print(length * 2)
print(length / 2)
print(length // 2)
print(length % 2)
print(length ** 2)

Check Type

type(length)                # <class 'int'>
isinstance(length, int)     # True

type() shows the exact type; isinstance() checks whether a value is that type (or a subclass of it), and is usually the better choice inside an if.

length = 5

print(type(length))
print(isinstance(length, int))

Convert to Integer

int("5")      # 5
int(5.9)      # 5   (truncates, doesn't round)
int(True)     # 1

int() converts a string of digits, or truncates a float toward zero (it cuts off the decimal — it does not round).

print(int("5"))
print(int(5.9))
print(int(True))

Floats

A float is a number with a decimal point — for anything that isn't a whole number.

weight = 4.5

print(weight)

Arithmetic

weight + 1.5    # 6.0
weight / 2      # 2.25
10 / 2          # 5.0  (still a float, even though it divides evenly)

Floats support the same operators as integers. Notably, / always returns a float — even 10 / 2, which divides evenly, gives 5.0, not 5.

weight = 4.5

print(weight + 1.5)
print(weight / 2)
print(10 / 2)

Rounding

round(weight)         # 4  (Python rounds .5 to the nearest *even* number)
round(4.567, 2)        # 4.57

round() with no second argument rounds to the nearest whole number — but Python uses "round half to even" (banker's rounding), so round(4.5) is 4, not 5. Pass a second argument to round to that many decimal places instead.

weight = 4.5
print(round(weight))
print(round(4.567, 2))

Convert to Float

float(5)         # 5.0
float("4.5")      # 4.5

float() converts an integer or a numeric string into a float.

print(float(5))
print(float("4.5"))

Floating-Point Precision

0.1 + 0.2    # 0.30000000000000004

Floats are stored in binary, and most decimal fractions (like 0.1) can't be represented exactly in binary — so tiny rounding errors creep in during arithmetic. This is a property of floating-point math in virtually every programming language, not a Python bug. If you need exact decimal arithmetic (for money, for example), use the decimal module instead of float.

print(0.1 + 0.2)
print(round(0.1 + 0.2, 2))

Strings

A string stores text — a sequence of characters — inside a single variable.

Strings have three defining traits:

  • Ordered — characters keep the position they're written in.
  • Immutable — unlike a list, a string can't be changed in place; every "modification" actually builds a new string.
  • Indexable — since a string is a sequence, it supports the same [] indexing and slicing as a list.
name = "burmese python"

print(name)

Access Characters

name[0]      # "b"
name[-1]     # "n"
name[0:7]    # "burmese"

Strings use the same index and slice syntax as lists — 0 for the first character, negative indexes count from the end, and start:end slices out a substring.

name = "burmese python"

print(name[0])
print(name[-1])
print(name[0:7])
print(name[8:])

Concatenate & Repeat

"ball" + " " + "python"    # "ball python"
"ball" * 3                  # "ballballball"

+ joins strings end to end.

* repeats a string a given number of times.

species = "ball"
name = species + " " + "python"
print(name)

print(species * 3)

Format Strings

f"the {species} python is about {length} feet long"    # "the ball python is about 5 feet long"

An f-string (a string literal prefixed with f) lets you embed variables and expressions directly inside {}, without manually joining pieces with +.

species = "ball"
length = 5
sentence = f"the {species} python is about {length} feet long"
print(sentence)

Modify Strings

name.upper()          # "BURMESE PYTHON"
name.title()          # "Burmese Python"
"  ball  ".strip()    # "ball"
name.replace("burmese", "ball")   # "ball python"

upper(), lower(), and title() change letter case — and since strings are immutable, each returns a new string rather than changing the original.

strip() removes leading and trailing whitespace.

replace() swaps every occurrence of one substring for another.

name = "burmese python"

print(name.upper())
print(name.title())

padded = "  ball python  "
print(padded.strip())

print(name.replace("burmese", "ball"))

Split & Join

name.split()                          # ["burmese", "python"]
"-".join(["burmese", "python"])       # "burmese-python"

split() breaks a string into a list, using whitespace as the separator by default.

join() does the reverse — it glues a list of strings back together, using the string it's called on as the separator between each item.

name = "burmese python"
parts = name.split()
print(parts)

rejoined = "-".join(parts)
print(rejoined)

Check Substring

"python" in name          # True
name.find("python")       # 8
name.count("p")           # 1

Use in to check whether one string contains another.

find() returns the index where a substring first appears, or -1 if it's not found.

count() counts how many times a substring appears.

name = "burmese python"

print("python" in name)
print("cobra" in name)

print(name.find("python"))
print(name.count("p"))

Convert to String

str(5)      # "5"
str(4.5)    # "4.5"
str(True)   # "True"

str() converts almost any value into its text representation — handy any time you need to combine a number with text, since + can't join a string and a number directly.

print(str(5))
print(str(4.5))
print(str(True))

Booleans

A boolean (bool) holds one of exactly two values, True or False — used to represent yes/no, on/off, or the result of a comparison.

venomous = False

print(venomous)

Comparisons Return Booleans

length = 5
length > 3     # True
length == 5    # True
length != 5    # False

Every comparison operator (>, <, >=, <=, ==, !=) evaluates to a bool — this is what powers every if statement.

length = 5

print(length > 3)
print(length == 5)
print(length != 5)

Combine Booleans

is_python and is_venomous    # True and False → False
is_python or is_venomous     # True or False  → True
not is_venomous              # not False      → True

and is True only if both sides are; or is True if either side is; not flips a boolean.

is_python = True
is_venomous = False

print(is_python and is_venomous)
print(is_python or is_venomous)
print(not is_venomous)

Truthy & Falsy Values

bool(0)       # False
bool("")      # False
bool([])      # False
bool(None)    # False
bool("ball")  # True
bool(5)       # True

Every value in Python is "truthy" or "falsy" when used somewhere a boolean is expected, like an if. Zero, empty strings, empty collections, and None are all falsy; almost everything else — including any non-empty string or nonzero number — is truthy.

print(bool(0))
print(bool(""))
print(bool([]))
print(bool(None))

print(bool("ball"))
print(bool(5))

Bool Is a Subclass of Int

isinstance(True, int)    # True
True + True               # 2

bool is technically a subclass of intTrue behaves like 1 and False behaves like 0 in arithmetic, though it's rare to rely on this on purpose.

print(isinstance(True, int))
print(True + True)

None

None represents the absence of a value — Python's way of saying "nothing here," distinct from 0, False, or an empty string.

venomous = None

print(venomous)

Check Type

type(venomous)    # <class 'NoneType'>

None is the only value of its own type, NoneType.

venomous = None
print(type(venomous))

Check for None

venomous is None        # True
venomous is not None    # False

Always compare to None with is / is not, not == / !=is checks that it's the exact same object, which is what you want for a singleton value like None, and avoids surprising results from custom __eq__ methods.

venomous = None

print(venomous is None)
print(venomous is not None)

Functions Return None by Default

result = find_species("cobra")    # None — the function fell through without a return

If a function runs to the end without hitting a return statement, it returns None automatically — this is what you get back if a lookup silently "doesn't find" anything.

def find_species(name):
    if name == "ball":
        return "found it"
    # falls through here for anything else — implicitly returns None

result = find_species("cobra")
print(result)
print(result is None)