Data Types and Variables

Every piece of data in a program has a type. Understanding data types is fundamental - they determine what operations are valid, how data is stored in memory, and how much space it requires.

1. What are Data Types?

A data type defines:

  • What values a piece of data can hold
  • What operations can be performed on it
  • How it's represented in memory

Why Types Matter

# These look similar but behave differently
a = "5"      # String
b = 5        # Integer

print(a + a)  # "55" (string concatenation)
print(b + b)  # 10 (addition)

2. Primitive Data Types

Primitive types are the basic building blocks provided by a language.

Integers

Whole numbers (positive, negative, or zero).

age = 25
temperature = -10
count = 0

# Python has arbitrary precision integers
big_number = 12345678901234567890
print(big_number * 2)  # Works perfectly!

Common operations:

a = 10
b = 3

print(a + b)   # 13 (addition)
print(a - b)   # 7 (subtraction)
print(a * b)   # 30 (multiplication)
print(a / b)   # 3.333... (true division)
print(a // b)  # 3 (floor division)
print(a % b)   # 1 (modulo - remainder)
print(a ** b)  # 1000 (exponentiation)

Floating-Point Numbers

Numbers with decimal points.

pi = 3.14159
price = 19.99
scientific = 6.022e23  # 6.022 × 10²³

Important: Floating-point has precision limits!

print(0.1 + 0.2)  # 0.30000000000000004 (not exactly 0.3!)

# Why? Binary can't represent 0.1 exactly, just like
# decimal can't represent 1/3 exactly (0.333...)

# For money, use integers (cents) or Decimal
from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2'))  # 0.3 (exact)

Booleans

True or False values.

is_student = True
is_employed = False

# Boolean operations
print(True and False)   # False
print(True or False)    # True
print(not True)         # False

# Comparison operators return booleans
print(5 > 3)    # True
print(5 == 5)   # True
print(5 != 3)   # True

None / Null

Represents the absence of a value.

result = None

if result is None:
    print("No result yet")

3. Strings

Strings are sequences of characters.

name = "Alice"
message = 'Hello, World!'
multiline = """This is a
multi-line string"""

# Empty string
empty = ""

String Operations

first = "Hello"
last = "World"

# Concatenation
full = first + " " + last    # "Hello World"

# Repetition
laugh = "ha" * 3             # "hahaha"

# Length
print(len(first))            # 5

# Indexing (0-based)
print(first[0])              # "H"
print(first[-1])             # "o" (last character)

# Slicing
print(first[1:4])            # "ell"
print(first[:3])             # "Hel" (first 3)
print(first[2:])             # "llo" (from index 2)

String Methods

text = "  Hello, World!  "

print(text.lower())          # "  hello, world!  "
print(text.upper())          # "  HELLO, WORLD!  "
print(text.strip())          # "Hello, World!" (remove whitespace)
print(text.replace("World", "Python"))  # "  Hello, Python!  "
print(text.split(","))       # ["  Hello", " World!  "]

# Checking content
print("Hello" in text)       # True
print(text.startswith("  H"))  # True
print(text.isdigit())        # False

String Formatting

name = "Alice"
age = 25

# f-strings (Python 3.6+, recommended)
message = f"My name is {name} and I am {age} years old"

# format method
message = "My name is {} and I am {} years old".format(name, age)

# % formatting (older style)
message = "My name is %s and I am %d years old" % (name, age)

# Formatting numbers
pi = 3.14159
print(f"Pi is approximately {pi:.2f}")  # "Pi is approximately 3.14"

price = 1234.5
print(f"Price: ${price:,.2f}")  # "Price: $1,234.50"

Strings are Immutable

s = "Hello"
# s[0] = "h"  # Error! Can't modify strings

# Create a new string instead
s = "h" + s[1:]  # "hello"

4. Variables

A variable is a named reference to a value stored in memory.

Declaration and Assignment

# Python infers the type
x = 10          # x is an integer
x = "hello"     # Now x is a string (Python allows this)

# Multiple assignment
a, b, c = 1, 2, 3

# Swap values
a, b = b, a

Naming Rules and Conventions

Rules (must follow):

  • Start with letter or underscore
  • Contain only letters, numbers, underscores
  • Case-sensitive (nameName)
  • Cannot be a reserved keyword

Conventions (should follow):

# Variables: snake_case
user_name = "alice"
total_count = 100

# Constants: UPPER_SNAKE_CASE
MAX_SIZE = 1000
PI = 3.14159

# Private (by convention): leading underscore
_internal_value = 42

# Avoid:
l = 1  # Looks like 1
O = 0  # Looks like 0

Scope

Variables have a scope - where they can be accessed.

global_var = "I'm global"

def my_function():
    local_var = "I'm local"
    print(global_var)   # Can access global
    print(local_var)    # Can access local

my_function()
print(global_var)       # Works
# print(local_var)      # Error! local_var doesn't exist here

5. Type Systems

Static vs Dynamic Typing

Static typing: Types checked at compile time

// Java (static)
int x = 5;
x = "hello";  // Compile error!

Dynamic typing: Types checked at runtime

# Python (dynamic)
x = 5
x = "hello"  # Fine! x is now a string

Strong vs Weak Typing

Strong typing: Limited implicit conversions

# Python is strongly typed
x = "5" + 3  # Error! Can't add string and int

Weak typing: More implicit conversions

// JavaScript is weakly typed
x = "5" + 3  // "53" (3 becomes "3")

Type Hints in Python

Python 3.5+ supports optional type hints:

def greet(name: str) -> str:
    return f"Hello, {name}"

age: int = 25
names: list[str] = ["Alice", "Bob"]

Type hints are not enforced at runtime but help with documentation and can be checked with tools like mypy.


6. Type Conversion

Implicit Conversion

Python automatically converts in some cases:

x = 5       # int
y = 2.0     # float
z = x + y   # 7.0 (int promoted to float)

Explicit Conversion (Casting)

# To integer
int("42")       # 42
int(3.7)        # 3 (truncates, doesn't round)
int("3.7")      # Error! Can't parse directly

# To float
float("3.14")   # 3.14
float(42)       # 42.0

# To string
str(42)         # "42"
str(3.14)       # "3.14"
str(True)       # "True"

# To boolean
bool(0)         # False
bool(42)        # True (any non-zero is True)
bool("")        # False (empty string)
bool("hello")   # True (non-empty string)
bool([])        # False (empty list)
bool([1,2])     # True (non-empty list)

7. Composite Types Preview

Beyond primitives, languages offer ways to group data:

Lists (Arrays)

Ordered, mutable collections:

numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]

print(numbers[0])      # 1
numbers.append(6)      # [1, 2, 3, 4, 5, 6]
numbers[0] = 10        # [10, 2, 3, 4, 5, 6]

Tuples

Ordered, immutable collections:

point = (3, 4)
rgb = (255, 128, 0)

x, y = point           # Unpacking
# point[0] = 5         # Error! Tuples are immutable

Dictionaries (Maps)

Key-value pairs:

person = {
    "name": "Alice",
    "age": 25,
    "city": "Boston"
}

print(person["name"])  # "Alice"
person["age"] = 26     # Update value
person["job"] = "Engineer"  # Add new key

Sets

Unordered collections of unique elements:

numbers = {1, 2, 3, 2, 1}  # {1, 2, 3}
print(2 in numbers)        # True

a = {1, 2, 3}
b = {2, 3, 4}
print(a | b)  # Union: {1, 2, 3, 4}
print(a & b)  # Intersection: {2, 3}

8. Memory and References

How Variables Work

Variables in Python are references to objects in memory:

a = [1, 2, 3]
b = a          # b refers to the SAME list

b.append(4)
print(a)       # [1, 2, 3, 4] - a is affected!

# To make a copy:
c = a.copy()   # or list(a) or a[:]
c.append(5)
print(a)       # [1, 2, 3, 4] - a is NOT affected

Identity vs Equality

a = [1, 2, 3]
b = [1, 2, 3]
c = a

print(a == b)  # True (same value)
print(a is b)  # False (different objects)
print(a is c)  # True (same object)

# id() shows memory address
print(id(a))   # e.g., 140234567890
print(id(c))   # Same as above
print(id(b))   # Different

Small Integer Caching

Python caches small integers (-5 to 256):

a = 100
b = 100
print(a is b)  # True (same cached object)

a = 1000
b = 1000
print(a is b)  # False (different objects)

Exercises

Basic

  1. What is the type of each variable?
a = 42
b = 3.14
c = "hello"
d = True
e = None
f = [1, 2, 3]
  1. What does each expression evaluate to?
10 + 3
10 - 3
10 * 3
10 / 3
10 // 3
10 % 3
10 ** 3
  1. Fix the errors:
print("The answer is " + 42)
name = "Alice
age = twenty-five

Intermediate

  1. Write code that:

    • Takes a temperature in Celsius
    • Converts it to Fahrenheit: F = C × 9/5 + 32
    • Prints the result formatted to 1 decimal place
  2. What happens with each conversion? Predict, then test:

int(3.9)
int("3.9")
float("hello")
bool([])
bool([0])
str([1, 2, 3])
  1. Explain why this happens:
a = [1, 2, 3]
b = a
b.append(4)
print(a)  # What prints?

Advanced

  1. Research: What is the largest integer Python can handle? What about floats?

  2. Investigate floating-point issues:

# Why do these give different results?
sum([0.1] * 10)
0.1 * 10
  1. Create a simple program that:
    • Stores person data in a dictionary
    • Has at least 4 fields (name, age, height, is_student)
    • Prints a formatted summary

Summary

  • Data types determine what values and operations are valid
  • Primitive types: integers, floats, booleans, None
  • Strings are immutable sequences of characters
  • Variables are references to values in memory
  • Python is dynamically typed (types checked at runtime)
  • Python is strongly typed (limited implicit conversions)
  • Use explicit conversion (casting) when needed
  • Collections (lists, tuples, dicts, sets) group data together

Next Reading

Control Structures →