Python variables and data types are the naming system and value-classification rules that let a Python program store, label, and correctly operate on every piece of information it handles — from a single number to a full dictionary of user records. In the previous lesson, you installed Python and wrote your first program using print() and input() — now it's time to understand how Python actually remembers and organizes information.
This matters because every bug you'll hit later — a crashed calculation, a silently wrong comparison, a function that mysteriously "remembers" data it shouldn't — traces back to a shaky grasp of exactly this topic. A solid understanding of variables and data types will make everything you build afterward (functions, loops, APIs, data pipelines) gets easier to reason about.
In This Post
- 1. Python Variables — Your Data Containers
- 2. Python Data Types Overview
- 3. Python Numbers: int, float, and Arithmetic
- 4. Python Type Casting (Converting Between Types)
- 5. Python Strings: Text, Slicing, and Formatting
- 6. Python Booleans: True, False, and Logic
- 7. Python None: Representing "No Value"
- 8. Final Project: Student Management System
- 9. Quick Reference Cheat Sheet
- 10. Common Pitfalls (And How to Avoid Them)
- 11. Practice Exercises
- 12. FAQ
- 13. References & Further Reading
- 14. Summary
Quick Comparison: Python's Core Data Types at a Glance
Before the deep dive, here's a bird's-eye view of the five fundamentals this lesson covers. Keep this table handy as you read through each section below.
| Type | Mutable? | Example Literal | Typical Use |
|---|---|---|---|
int | No | 42 | Whole numbers, counters, IDs |
float | No | 3.14 | Measurements, decimals, math |
str | No | "hello" | Text, names, messages |
bool | No | True | Conditions, yes/no flags |
NoneType | No | None | Deliberate "no value yet" |
1. Python Variables — Your Data Containers
A simple analogy
Imagine you're organizing your kitchen. You have containers labeled "Sugar," "Salt," "Flour" — each container holds a specific thing, and the label tells you what's inside without you having to look. Variables work the same way in Python: they're named containers that store data so you can find and use it later.
What is a Variable?
A variable is a name that points to a value stored in your computer's memory.
Instead of remembering that your age is stored at memory location 0x7f9e3c4a1b20, you just use a friendly name like age.
# Creating a variable is this simple:
age = 25
# Now 'age' stores the value 25
print(age) # Output: 25
Creating Variables — The Basics
In Python, you create variables using the assignment operator =.
Syntax: variable_name = value
# Different types of variables
name = "Alice" # Text (string)
age = 25 # Whole number (integer)
height = 5.6 # Decimal number (float)
is_student = True # True/False (boolean)
# Using variables
print(f"My name is {name}")
print(f"I am {age} years old")
print(f"My height is {height} feet")
print(f"Student status: {is_student}")
Output:
My name is Alice
I am 25 years old
My height is 5.6 feet
Student status: True
You don't need to tell Python what type of data you're storing. Python figures it out automatically! This is called dynamic typing.
x = y doesn't copy data; it makes y point to the same object x already refers to. For str, int, float, and bool (all immutable), this distinction is invisible in daily use — but it becomes very important once you work with mutable types like lists later in this series.
Variable Naming Rules
Not all names are valid. Python has strict rules:
user_name = "Alice" # Snake case (recommended)
userName = "Bob" # Camel case (works but not Pythonic)
_private_var = 42 # Leading underscore (special meaning)
user1 = "Charlie" # Numbers allowed (but not at start)
USER_CONSTANT = 100 # All caps (for constants)
my_var2 = "valid" # Mix of letters and numbers
Rules that make names valid:
- Start with letter (a-z, A-Z) or underscore (_)
- Can contain letters, numbers, and underscores
- Case-sensitive (age ≠ Age ≠ AGE)
- No spaces allowed
2nd_value = 10 # Error! Can't start with number
user-name = "Alice" # Error! Hyphens not allowed
user name = "Bob" # Error! Spaces not allowed
class = "Math" # Error! 'class' is reserved keyword
for = 10 # Error! 'for' is reserved keyword
user@email = "x@y.com" # Error! Special characters not allowed
Common mistakes to avoid:
- Starting with numbers
- Using hyphens instead of underscores
- Including spaces
- Using reserved keywords (if, else, for, while, etc.)
Variable Naming Conventions
Following conventions makes your code professional and readable.
# Snake case (recommended for variables and functions)
first_name = "Alice"
total_price = 99.99
is_valid_email = True
# SCREAMING_SNAKE_CASE (for constants)
MAX_LOGIN_ATTEMPTS = 3
PI_VALUE = 3.14159
DATABASE_URL = "localhost:5432"
# PascalCase (reserved for class names)
class UserAccount:
pass
class ShoppingCart:
pass
Use descriptive names that explain what the variable holds.
user_email is infinitely better than ue or x. Clear names also make code easier to review and maintain.
Multiple Assignment
Python lets you create multiple variables in one line. This is useful when several related values need to be assigned together.
# Assign same value to multiple variables
x = y = z = 0
print(x, y, z) # Output: 0 0 0
# Assign different values to multiple variables
name, age, city = "Alice", 25, "New York"
print(name) # Output: Alice
print(age) # Output: 25
print(city) # Output: New York
# Unpacking a list
coordinates = [10, 20, 30]
x, y, z = coordinates
print(f"X: {x}, Y: {y}, Z: {z}") # Output: X: 10, Y: 20, Z: 30
Reassigning Variables
Variables can change their values anytime. They're called "variables" for a reason!
# Initial value
score = 0
print(f"Score: {score}") # Output: Score: 0
# Update value
score = 10
print(f"Score: {score}") # Output: Score: 10
# Update using current value
score = score + 5
print(f"Score: {score}") # Output: Score: 15
# Shorthand for update
score += 10 # Same as: score = score + 10
print(f"Score: {score}") # Output: Score: 25
Variables Can Change Type!
Unlike some languages, Python variables can change their data type.
# Start as integer
value = 42
print(value, type(value)) # Output: 42 <class 'int'>
# Change to string
value = "Hello"
print(value, type(value)) # Output: Hello <class 'str'>
# Change to float
value = 3.14
print(value, type(value)) # Output: 3.14 <class 'float'>
Just because you can change a variable's type doesn't mean you should. It can make code confusing. Best practice: Keep each variable's type consistent.
Deleting Variables
Use del to remove a variable from memory:
temp_value = 100
print(temp_value) # Output: 100
del temp_value
print(temp_value) # Error! NameError: name 'temp_value' is not defined
Use this when...
You need to store, label, or refer back to any piece of information in your program — a user's input, a running total, a configuration flag, or the result of a calculation.
2. Python Data Types Overview
Every value in Python has a type. The type determines what you can do with that value.
A simple analogy
Think of data types like categories of items in a store: groceries are for cooking, electronics turn on and off, and books are for reading. You wouldn't try to "turn on" a book — and Python feels the same way about mixing up its types. Every data type supports its own specific set of operations.
Python's Built-in Data Types
Python has several categories of data types:
# Text Type
str # "Hello", 'Python', """Multi-line"""
# Numeric Types
int # 42, -17, 1000000
float # 3.14, -0.5, 2.0
complex # 3+4j (we'll skip this for now)
# Boolean Type
bool # True, False
# None Type
NoneType # None (absence of value)
# Sequence Types
list # [1, 2, 3]
tuple # (1, 2, 3)
range # range(0, 10)
# Mapping Type
dict # {"name": "Alice", "age": 25}
# Set Types
set # {1, 2, 3}
frozenset # frozenset({1, 2, 3})
Today we'll focus on the fundamental types: str, int, float, bool, and None.
Checking Data Types
Use the type() function to check what type a variable is:
name = "Alice"
age = 25
height = 5.6
is_student = True
nothing = None
print(type(name)) # <class 'str'>
print(type(age)) # <class 'int'>
print(type(height)) # <class 'float'>
print(type(is_student)) # <class 'bool'>
print(type(nothing)) # <class 'NoneType'>
Type Checking with isinstance()
To check if a variable is a specific type, use isinstance():
age = 25
print(isinstance(age, int)) # True
print(isinstance(age, str)) # False
print(isinstance(age, float)) # False
# Check multiple types at once
value = 42
print(isinstance(value, (int, float))) # True (it's an int)
Use this when...
You're deciding what a piece of data actually represents — reach for type() when debugging, and isinstance() whenever your code needs to branch based on what kind of value it just received.
3. Python Numbers — Working with Numeric Data
A simple analogy
An integer is like counting whole marbles — you can have 3 or 12, but never "half a marble." A float is like pouring juice into a measuring cup — you can have exactly 3.5 fluid ounces, capturing amounts in between the whole numbers.
Numbers are everywhere in programming. Python has three main numeric types: int, float, and complex.
Integers (int) - Whole Numbers
Integers are whole numbers without decimal points.
# Positive integers
age = 25
year = 2024
population = 8000000000
# Negative integers
temperature = -10
debt = -5000
# Zero
nothing = 0
# Integers can be HUGE in Python (no limit!)
gigantic = 123456789012345678901234567890
print(gigantic) # Python handles it perfectly!
Unlike many languages, Python integers have unlimited precision. You can work with numbers as large as your computer's memory allows! No "integer overflow" errors.
Integer Literals in Different Bases
You can write integers in different number systems:
# Decimal (base 10) - normal numbers
decimal = 42
# Binary (base 2) - prefix with 0b
binary = 0b101010 # Same as 42
print(binary) # Output: 42
# Octal (base 8) - prefix with 0o
octal = 0o52 # Same as 42
print(octal) # Output: 42
# Hexadecimal (base 16) - prefix with 0x
hexadecimal = 0x2A # Same as 42
print(hexadecimal) # Output: 42
Floats (float) - Decimal Numbers
Floats represent numbers with decimal points.
# Basic floats
price = 19.99
temperature = 98.6
pi = 3.14159
# Very small numbers
tiny = 0.0000001
# Scientific notation
speed_of_light = 3e8 # 3 × 10^8 = 300,000,000
planck_constant = 6.626e-34 # 6.626 × 10^-34
print(speed_of_light) # Output: 300000000.0
print(planck_constant) # Output: 6.626e-34
Floats have limited precision due to how computers store them.
result = 0.1 + 0.2
print(result) # Output: 0.30000000000000004 (not exactly 0.3!)
For financial calculations, use the decimal module instead.
Arithmetic Operations
Python supports all standard math operations:
# Addition
result = 10 + 5
print(result) # Output: 15
# Subtraction
result = 10 - 5
print(result) # Output: 5
# Multiplication
result = 10 * 5
print(result) # Output: 50
# Division (always returns float)
result = 10 / 3
print(result) # Output: 3.3333333333333335
# Floor Division (returns integer, rounds down)
result = 10 // 3
print(result) # Output: 3
# Modulus (remainder)
result = 10 % 3
print(result) # Output: 1
# Exponentiation (power)
result = 2 ** 3
print(result) # Output: 8 (2³ = 8)
Operator Precedence
Python follows PEMDAS (Parentheses, Exponents, Multiplication/Division, Addition/Subtraction):
# Without parentheses
result = 10 + 5 * 2
print(result) # Output: 20 (multiplication first: 10 + 10)
# With parentheses
result = (10 + 5) * 2
print(result) # Output: 30 (parentheses first: 15 * 2)
# Complex example
result = 10 + 5 * 2 ** 2 - 3
# Order: 2**2 = 4, then 5*4 = 20, then 10+20-3 = 27
print(result) # Output: 27
Augmented Assignment Operators
Shortcuts for updating variables:
score = 10
# Long way
score = score + 5
# Short way (augmented assignment)
score += 5 # Add 5
score -= 3 # Subtract 3
score *= 2 # Multiply by 2
score /= 4 # Divide by 4
score //= 2 # Floor divide by 2
score %= 3 # Modulus by 3
score **= 2 # Raise to power 2
print(score)
Built-in Math Functions
Python has useful built-in functions for numbers:
# Absolute value
print(abs(-42)) # Output: 42
print(abs(42)) # Output: 42
# Rounding
print(round(3.7)) # Output: 4
print(round(3.4)) # Output: 3
print(round(3.14159, 2)) # Output: 3.14 (2 decimal places)
# Power
print(pow(2, 3)) # Output: 8 (same as 2**3)
# Min and Max
print(min(5, 2, 8, 1)) # Output: 1
print(max(5, 2, 8, 1)) # Output: 8
# Sum
numbers = [1, 2, 3, 4, 5]
print(sum(numbers)) # Output: 15
Math Module for Advanced Operations
import math
# Constants
print(math.pi) # Output: 3.141592653589793
print(math.e) # Output: 2.718281828459045
# Square root
print(math.sqrt(16)) # Output: 4.0
# Trigonometry
print(math.sin(math.pi/2)) # Output: 1.0
print(math.cos(0)) # Output: 1.0
# Logarithms
print(math.log(10)) # Natural log
print(math.log10(100)) # Output: 2.0
# Ceiling and Floor
print(math.ceil(3.2)) # Output: 4 (round up)
print(math.floor(3.8)) # Output: 3 (round down)
Practical Number Examples
Example 1: Calculate Circle Area
import math
radius = 5
area = math.pi * radius ** 2
circumference = 2 * math.pi * radius
print(f"Circle with radius {radius}:")
print(f"Area: {area:.2f} square units")
print(f"Circumference: {circumference:.2f} units")
# Output:
# Circle with radius 5:
# Area: 78.54 square units
# Circumference: 31.42 units
Example 2: Compound Interest Calculator
principal = 1000 # Initial amount
rate = 0.05 # 5% annual interest
time = 10 # Years
# A = P(1 + r)^t
final_amount = principal * (1 + rate) ** time
interest_earned = final_amount - principal
print(f"Initial Investment: ${principal:.2f}")
print(f"Interest Rate: {rate*100}%")
print(f"Time Period: {time} years")
print(f"Final Amount: ${final_amount:.2f}")
print(f"Interest Earned: ${interest_earned:.2f}")
# Output:
# Initial Investment: $1000.00
# Interest Rate: 5.0%
# Time Period: 10 years
# Final Amount: $1628.89
# Interest Earned: $628.89
Use this when...
You're modeling a quantity — a price, a count, a measurement — and need to pick int or float based on whether fractional values are meaningful for that quantity.
4. Python Casting — Converting Between Types
A simple analogy
Type casting is like converting a recipe from cups to grams before you can weigh the ingredients on a kitchen scale. The "amount" of flour you mean doesn't change — you're just re-expressing it in the unit your next tool actually understands.
Sometimes you need to convert data from one type to another. This is called type casting or type conversion.
Why Cast Types?
Common scenarios:
- User input is always a string, but you need a number
- Want to display a number as text
- Need to perform math on string numbers
- Combine different types in formatted output
Converting to Integer - int()
# String to integer
age_str = "25"
age_int = int(age_str)
print(age_int) # Output: 25
print(type(age_int)) # Output: <class 'int'>
# Float to integer (truncates decimal)
price = 19.99
price_int = int(price)
print(price_int) # Output: 19 (not 20!)
# Boolean to integer
print(int(True)) # Output: 1
print(int(False)) # Output: 0
# Can't convert non-numeric strings
age = int("twenty-five") # Error! ValueError
# Can't convert strings with decimals directly to int
price = int("19.99") # Error! ValueError
# Fix: Convert to float first, then int
price = int(float("19.99")) # Works! Output: 19
Converting to Float - float()
# String to float
price_str = "19.99"
price_float = float(price_str)
print(price_float) # Output: 19.99
# Integer to float
age = 25
age_float = float(age)
print(age_float) # Output: 25.0
# Boolean to float
print(float(True)) # Output: 1.0
print(float(False)) # Output: 0.0
# String integer to float
number = float("42")
print(number) # Output: 42.0
Converting to String - str()
# Integer to string
age = 25
age_str = str(age)
print(age_str) # Output: "25"
print(type(age_str)) # Output: <class 'str'>
# Float to string
price = 19.99
price_str = str(price)
print(price_str) # Output: "19.99"
# Boolean to string
status = True
status_str = str(status)
print(status_str) # Output: "True"
# Combining with concatenation
name = "Alice"
age = 25
message = name + " is " + str(age) + " years old"
print(message) # Output: "Alice is 25 years old"
Converting to Boolean - bool()
Boolean conversion is worth understanding because it appears throughout conditional code and validation.
# Numbers to boolean
print(bool(1)) # Output: True
print(bool(42)) # Output: True
print(bool(-5)) # Output: True
print(bool(0)) # Output: False (ONLY zero is False!)
print(bool(0.0)) # Output: False
# Strings to boolean
print(bool("Hello")) # Output: True
print(bool("False")) # Output: True (any non-empty string!)
print(bool("")) # Output: False (empty string is False)
# None to boolean
print(bool(None)) # Output: False
In Python, these values are considered False:
False(the boolean)0,0.0(numeric zero)""(empty string)[](empty list){}(empty dict)None
Implicit vs Explicit Conversion
Implicit (Automatic): Python converts automatically
# Python automatically converts int to float when needed
result = 10 + 3.5 # 10 becomes 10.0 automatically
print(result) # Output: 13.5
print(type(result)) # Output: <class 'float'>
Explicit (Manual): You convert using functions
# You must explicitly convert string to int
age_str = "25"
age_int = int(age_str) # Explicit conversion required
print(age_int + 5) # Output: 30
Practical Casting Examples
Example 1: User Input Calculator
# User input is always string - must convert!
num1_str = input("Enter first number: ")
num2_str = input("Enter second number: ")
# Convert to float for calculations
num1 = float(num1_str)
num2 = float(num2_str)
result = num1 + num2
print(f"Sum: {result}")
# User enters: 10.5 and 20.3
# Output: Sum: 30.8
Example 2: Age Validator
age_input = input("Enter your age: ")
try:
age = int(age_input)
if age >= 18:
print("You are an adult.")
else:
print(f"You are a minor. {18 - age} years until adulthood.")
except ValueError:
print("Invalid age! Please enter a number.")
Use this when...
You're bridging data across a boundary that only speaks strings — input(), environment variables, and most file or network data — and need real numbers or booleans before doing calculations or comparisons with them.
5. Python Strings — Working with Text
A simple analogy
A string is like a beaded necklace — each bead is one character, strung together in a fixed order. You can count the beads, point at any one of them, or snip out a section to look at — but you can't reach in and swap a single bead without re-stringing the whole necklace as a brand-new one.
Strings are sequences of characters enclosed in quotes. They're one of the most commonly used data types.
Creating Strings
You can use single quotes, double quotes, or triple quotes:
# Single quotes
name = 'Alice'
# Double quotes (exactly the same as single)
name = "Alice"
# Triple quotes (for multi-line strings)
message = """
This is a
multi-line
string.
"""
# When to use which?
# Use double quotes when string contains single quote
sentence = "It's a beautiful day!"
# Use single quotes when string contains double quote
quote = 'She said, "Hello!"'
# Or use escape characters
sentence = 'It\'s a beautiful day!'
quote = "She said, \"Hello!\""
String Basics
# Creating strings
greeting = "Hello, World!"
name = "Alice"
empty = ""
# String length
print(len(greeting)) # Output: 13
print(len(name)) # Output: 5
print(len(empty)) # Output: 0
String Indexing
Access individual characters using square brackets:
text = "Python"
# Positive indexing (starts at 0)
print(text[0]) # Output: P (first character)
print(text[1]) # Output: y
print(text[5]) # Output: n (last character)
# Negative indexing (starts from end)
print(text[-1]) # Output: n (last character)
print(text[-2]) # Output: o (second to last)
print(text[-6]) # Output: P (first character)
# Visual representation:
# P y t h o n
# 0 1 2 3 4 5 (positive index)
# -6 -5 -4 -3 -2 -1 (negative index)
String Slicing
Extract portions of strings using [start:end:step]:
text = "Python Programming"
# Basic slicing [start:end] (end not included)
print(text[0:6]) # Output: Python
print(text[7:18]) # Output: Programming
# Omit start (defaults to 0)
print(text[:6]) # Output: Python
# Omit end (goes to end of string)
print(text[7:]) # Output: Programming
# Negative indices
print(text[-11:]) # Output: Programming
# Step (every nth character)
print(text[::2]) # Output: Pto rgamn (every 2nd char)
print(text[::-1]) # Output: gnimmargorP nohtyP (reversed!)
# Get every 3rd character
print(text[::3]) # Output: Ph oai
text[::-1] is the easiest way to reverse a string!
text[::3] outputs "Ph ormn" — that's wrong. We ran it in a live Python interpreter: indices 0, 3, 6, 9, 12, 15 of "Python Programming" spell out P, h, (space), o, a, i, giving "Ph oai". Always test slicing yourself with print() if you're unsure — it takes two seconds and saves real confusion.
String Concatenation
# Using + operator
first_name = "Alice"
last_name = "Smith"
full_name = first_name + " " + last_name
print(full_name) # Output: Alice Smith
# Using * for repetition
laugh = "ha" * 3
print(laugh) # Output: hahaha
border = "=" * 20
print(border) # Output: ====================
# Cannot mix types!
age = 25
message = "I am " + str(age) # Must convert to string!
print(message) # Output: I am 25
String Methods
Strings come with many built-in methods:
text = " Hello, Python World! "
# Case conversion
print(text.upper()) # Output: HELLO, PYTHON WORLD!
print(text.lower()) # Output: hello, python world!
print(text.capitalize()) # Output: hello, python world!
print(text.title()) # Output: Hello, Python World!
# Remove whitespace
print(text.strip()) # Output: Hello, Python World!
print(text.lstrip()) # Output: Hello, Python World! (left)
print(text.rstrip()) # Output: Hello, Python World! (right)
# Replace
new_text = text.replace("Python", "Amazing")
print(new_text) # Output: Hello, Amazing World!
# Split into list
words = "apple,banana,orange".split(",")
print(words) # Output: ['apple', 'banana', 'orange']
# Join list into string
fruits = ['apple', 'banana', 'orange']
result = ", ".join(fruits)
print(result) # Output: apple, banana, orange
String Searching and Checking
text = "Python Programming is Fun"
# Check if substring exists
print("Python" in text) # Output: True
print("Java" in text) # Output: False
print("Fun" not in text) # Output: False
# Find position of substring
print(text.find("Programming")) # Output: 7 (starting index)
print(text.find("Java")) # Output: -1 (not found)
# Count occurrences
text2 = "banana"
print(text2.count("a")) # Output: 3
# Check string properties
print("hello".isalpha()) # Output: True (all letters)
print("hello123".isalpha()) # Output: False
print("12345".isdigit()) # Output: True (all digits)
print("hello".islower()) # Output: True
print("HELLO".isupper()) # Output: True
print(" ".isspace()) # Output: True
String Formatting (F-strings)
name = "Alice"
age = 25
gpa = 3.875
# Basic f-string
message = f"My name is {name} and I am {age} years old."
print(message)
# Output: My name is Alice and I am 25 years old.
# Expressions inside f-strings
print(f"Next year I'll be {age + 1} years old.")
# Output: Next year I'll be 26 years old.
# Formatting numbers
print(f"GPA: {gpa:.2f}") # Output: GPA: 3.88 (2 decimals)
# Padding and alignment
print(f"Name: {name:<10}|") # Output: Name: Alice |
print(f"Name: {name:>10}|") # Output: Name: Alice|
print(f"Name: {name:^10}|") # Output: Name: Alice |
F-strings require Python 3.6+. If you're on an older version, use
.format() instead — but virtually every modern setup ships 3.6 or newer, so f-strings are the safe default.
Escape Characters
# Newline
print("Line 1\nLine 2")
# Output:
# Line 1
# Line 2
# Tab
print("Name:\tAlice\nAge:\t25")
# Output:
# Name: Alice
# Age: 25
# Backslash
print("Path: C:\\Users\\Alice")
# Output: Path: C:\Users\Alice
# Quotes
print("She said, \"Hello!\"")
# Output: She said, "Hello!"
# Raw strings (ignore escape characters)
print(r"C:\Users\new\test")
# Output: C:\Users\new\test
Strings are Immutable
Strings cannot be changed after creation. Every string operation creates a NEW string.
text = "Hello"
# This doesn't modify the original string
text.upper()
print(text) # Output: Hello (unchanged!)
# You must assign to a new variable (or same variable)
text = text.upper()
print(text) # Output: HELLO
# You cannot change individual characters
text = "Hello"
text[0] = "J" # Error! TypeError: 'str' object does not support item assignment
# Instead, create a new string
text = "J" + text[1:]
print(text) # Output: Jello
Practical String Examples
Example 1: Email Validator
email = input("Enter your email: ")
# Basic validation
if "@" in email and "." in email:
parts = email.split("@")
username = parts[0]
domain = parts[1]
print(f"Username: {username}")
print(f"Domain: {domain}")
print("Email format looks valid!")
else:
print("Invalid email format!")
Example 2: Password Strength Checker
password = input("Enter password: ")
# Check password strength
has_upper = any(c.isupper() for c in password)
has_lower = any(c.islower() for c in password)
has_digit = any(c.isdigit() for c in password)
long_enough = len(password) >= 8
if has_upper and has_lower and has_digit and long_enough:
print("Strong password!")
else:
print("Weak password. Need:")
if not has_upper:
print("- At least one uppercase letter")
if not has_lower:
print("- At least one lowercase letter")
if not has_digit:
print("- At least one digit")
if not long_enough:
print("- Minimum 8 characters")
Use this when...
You're working with text — parsing it, cleaning it, searching it, or formatting it for display — which is most of what real-world Python programs spend their time doing.
6. Python Booleans — True or False
Booleans represent one of two values: True or False.
A simple analogy
Think of a boolean like a light switch — either ON or OFF, no in-between setting. Every yes/no question your program asks, from "is the user logged in?" to "did the file load?", collapses down to exactly one of these two positions.
Creating Booleans
# Boolean literals
is_active = True
is_admin = False
print(type(is_active)) # Output: <class 'bool'>
# Note: First letter must be capital!
# true = True # Error! 'true' is not defined
Boolean from Comparisons
Comparisons always return boolean values:
# Equality
print(5 == 5) # Output: True
print(5 == 3) # Output: False
# Inequality
print(5 != 3) # Output: True
print(5 != 5) # Output: False
# Greater than / Less than
print(10 > 5) # Output: True
print(10 < 5) # Output: False
print(10 >= 10) # Output: True
print(5 <= 3) # Output: False
# String comparison
print("apple" == "apple") # Output: True
print("Apple" == "apple") # Output: False (case-sensitive!)
print("apple" < "banana") # Output: True (alphabetical)
Logical Operators
Combine boolean values using and, or, not:
# AND - both must be True
print(True and True) # Output: True
print(True and False) # Output: False
print(False and False) # Output: False
# OR - at least one must be True
print(True or False) # Output: True
print(False or False) # Output: False
print(True or True) # Output: True
# NOT - reverses the value
print(not True) # Output: False
print(not False) # Output: True
Practical Boolean Logic
age = 25
has_license = True
has_car = False
# Check if can drive
can_drive = age >= 18 and has_license
print(f"Can drive: {can_drive}") # Output: Can drive: True
# Check if needs transportation
needs_ride = not has_car
print(f"Needs ride: {needs_ride}") # Output: Needs ride: True
# Complex condition
is_eligible = (age >= 21 and has_license) or has_car
print(f"Eligible: {is_eligible}") # Output: Eligible: True
Boolean in Conditionals
is_raining = True
have_umbrella = False
if is_raining and not have_umbrella:
print("You'll get wet!")
elif is_raining and have_umbrella:
print("Don't forget your umbrella!")
else:
print("Enjoy the weather!")
Truthy and Falsy Values
We covered this in casting, but it's crucial for booleans:
# These are all Falsy (evaluate to False)
print(bool(0)) # False
print(bool(0.0)) # False
print(bool("")) # False (empty string)
print(bool([])) # False (empty list)
print(bool({})) # False (empty dict)
print(bool(None)) # False
# These are all Truthy (evaluate to True)
print(bool(1)) # True
print(bool(-1)) # True (any non-zero number)
print(bool("hello")) # True (non-empty string)
print(bool([1, 2])) # True (non-empty list)
print(bool({"a": 1})) # True (non-empty dict)
Short-Circuit Evaluation
Python stops evaluating as soon as it knows the answer:
# AND - stops at first False
result = False and print("This won't run")
# print() never executes because False and anything = False
# OR - stops at first True
result = True or print("This won't run either")
# print() never executes because True or anything = True
# Practical use: avoid errors
user = None
name = user and user.name # Doesn't crash! Returns None
print(name) # Output: None
Practical Boolean Examples
Example 1: Login System
username = input("Username: ")
password = input("Password: ")
# Simulated database
correct_username = "alice"
correct_password = "secret123"
# Check credentials
is_valid = (username == correct_username) and (password == correct_password)
if is_valid:
print("Login successful!")
else:
print("Invalid credentials!")
Example 2: Age Range Checker
age = int(input("Enter your age: "))
is_child = age < 13
is_teen = 13 <= age < 20
is_adult = 20 <= age < 65
is_senior = age >= 65
print(f"Child: {is_child}")
print(f"Teen: {is_teen}")
print(f"Adult: {is_adult}")
print(f"Senior: {is_senior}")
Use this when...
You're writing any conditional logic, filtering data, or deciding which branch of an if/elif/else chain a program should follow — booleans are the currency every condition trades in.
7. Python None — The Absence of Value
None is a special value that represents "nothing" or "no value".
A simple analogy
Think of None like an empty gift box sitting under the tree — the box definitely exists, you can pick it up and shake it, but there's genuinely nothing inside yet.
What is None?
# Creating None
value = None
print(value) # Output: None
print(type(value)) # Output: <class 'NoneType'>
# None is a singleton (only one None exists)
print(None is None) # Output: True
When to Use None
Common use cases:
- Default values: When a variable has no value yet
- Function returns: When function has nothing to return
- Missing data: Represent absence of data
- Optional parameters: Default parameter values
# 1. Default values
user_email = None # Will be set later
if user_email is None:
user_email = input("Enter your email: ")
# 2. Function returns
def find_user(username):
# Simulated search
if username == "alice":
return {"name": "Alice", "age": 25}
else:
return None # User not found
result = find_user("bob")
if result is None:
print("User not found!")
else:
print(f"Found: {result}")
# 3. Missing data
user_data = {
"name": "Alice",
"age": 25,
"email": None # Email not provided
}
# 4. Optional parameters
def greet(name, title=None):
if title is None:
print(f"Hello, {name}!")
else:
print(f"Hello, {title} {name}!")
greet("Alice") # Output: Hello, Alice!
greet("Smith", "Dr.") # Output: Hello, Dr. Smith!
Checking for None
value = None
# Use 'is' operator
if value is None:
print("Value is None")
# Check if NOT None
if value is not None:
print("Value exists")
# Don't use == with None
if value == None: # Works, but not recommended
print("Value is None")
Use is instead of == when checking for None! Since None is a singleton, is checks true object identity — it's both the idiomatic convention and marginally faster.
None vs Empty Values
Understanding the difference is important:
# These are different!
none_value = None
empty_string = ""
zero_value = 0
empty_list = []
print(none_value is None) # True
print(empty_string is None) # False
print(zero_value is None) # False
print(empty_list is None) # False
# But they're all Falsy
print(bool(none_value)) # False
print(bool(empty_string)) # False
print(bool(zero_value)) # False
print(bool(empty_list)) # False
None in Boolean Context
user = None
# None is Falsy
if not user:
print("No user logged in")
# But be careful!
user = "" # Empty string, not None
if not user: # This also triggers!
print("This prints too!")
# Better: explicitly check for None
if user is None:
print("No user (correctly checked)")
Practical None Examples
Example 1: Configuration System
class Config:
def __init__(self):
self.api_key = None
self.database_url = None
self.debug_mode = None
def is_configured(self):
return (
self.api_key is not None and
self.database_url is not None and
self.debug_mode is not None
)
config = Config()
print(f"Ready: {config.is_configured()}") # Output: Ready: False
config.api_key = "abc123"
config.database_url = "localhost:5432"
config.debug_mode = True
print(f"Ready: {config.is_configured()}") # Output: Ready: True
Example 2: Search with Default
def get_user_preference(user_id, preference_key, default=None):
"""
Get user preference, return default if not found
"""
# Simulated database
preferences = {
1: {"theme": "dark", "language": "en"},
2: {"theme": "light"}
}
user_prefs = preferences.get(user_id)
if user_prefs is None:
return default
return user_prefs.get(preference_key, default)
# Usage
theme = get_user_preference(1, "theme", "light")
print(f"Theme: {theme}") # Output: Theme: dark
language = get_user_preference(2, "language", "en")
print(f"Language: {language}") # Output: Language: en (default)
email = get_user_preference(3, "email", "none@example.com")
print(f"Email: {email}") # Output: Email: none@example.com
Use this when...
You need a placeholder for "not set yet," a function return value that means "nothing found," or a default parameter value that a function can detect and replace — never use it to mean "empty" when you actually mean an empty string, list, or zero.
8. Putting It All Together — Final Project
Now we can combine these ideas in one small student-management program.
"""
Student Management System
Demonstrates: variables, data types, casting, strings, booleans, None
"""
print("=" * 50)
print(" STUDENT MANAGEMENT SYSTEM")
print("=" * 50)
# Student data storage
students = []
while True:
print("\n--- Add Student ---")
# Get student name (string)
name = input("Student name (or 'done' to finish): ").strip()
if name.lower() == 'done':
break
if not name: # Check for empty string
print("Name cannot be empty!")
continue
# Get age (casting string to int)
age_input = input("Age: ").strip()
try:
age = int(age_input)
if age < 5 or age > 100:
print("Age must be between 5 and 100!")
continue
except ValueError:
print("Invalid age! Please enter a number.")
continue
# Get GPA (casting string to float)
gpa_input = input("GPA (0.0-4.0): ").strip()
try:
gpa = float(gpa_input)
if gpa < 0.0 or gpa > 4.0:
print("GPA must be between 0.0 and 4.0!")
continue
except ValueError:
print("Invalid GPA! Please enter a number.")
continue
# Get scholarship status (boolean)
scholarship_input = input("Has scholarship? (yes/no): ").strip().lower()
has_scholarship = scholarship_input == 'yes'
# Get email (string, optional - can be None)
email = input("Email (optional, press Enter to skip): ").strip()
if not email:
email = None
# Create student record (dictionary)
student = {
'name': name,
'age': age,
'gpa': gpa,
'has_scholarship': has_scholarship,
'email': email
}
students.append(student)
print(f"✓ Added {name} to the system!")
# Display summary
print("\n" + "=" * 50)
print(" STUDENT SUMMARY")
print("=" * 50)
if not students: # Empty list is Falsy
print("No students registered.")
else:
print(f"\nTotal students: {len(students)}\n")
for i, student in enumerate(students, 1):
print(f"{i}. {student['name'].upper()}")
print(f" Age: {student['age']}")
print(f" GPA: {student['gpa']:.2f}")
print(f" Scholarship: {'Yes' if student['has_scholarship'] else 'No'}")
# Handle None email
if student['email'] is None:
print(f" Email: Not provided")
else:
print(f" Email: {student['email']}")
# Calculate status
if student['gpa'] >= 3.5:
status = "Excellent"
elif student['gpa'] >= 3.0:
status = "Good"
elif student['gpa'] >= 2.0:
status = "Satisfactory"
else:
status = "Needs Improvement"
print(f" Status: {status}")
print()
# Statistics
total_gpa = sum(s['gpa'] for s in students)
average_gpa = total_gpa / len(students)
scholarship_count = sum(1 for s in students if s['has_scholarship'])
print("-" * 50)
print(f"Average GPA: {average_gpa:.2f}")
print(f"Students with scholarship: {scholarship_count}/{len(students)}")
print("=" * 50)
print("\nThank you for using Student Management System!")
9. Quick Reference Guide
Variables:
name = "Alice" # Create variable
age = age + 1 # Update variable
x = y = z = 0 # Multiple assignment
a, b, c = 1, 2, 3 # Unpack values
Type Checking:
type(variable) # Get type
isinstance(var, int) # Check if specific type
Casting:
int("42") # String to int
float("3.14") # String to float
str(42) # Number to string
bool(1) # To boolean
String Operations:
len(s) # Length
s.upper() # Uppercase
s.lower() # Lowercase
s.strip() # Remove whitespace
s.split(",") # Split by delimiter
",".join(list) # Join list into string
s[0:5] # Slice
s[::-1] # Reverse
Boolean Logic:
and # Both must be True
or # At least one True
not # Reverse boolean
is None # Check for None
10. Common Pitfalls and How to Avoid Them
# Bad
if 0.1 + 0.2 == 0.3: # False! (floating point precision)
print("Equal")
# Good
if abs((0.1 + 0.2) - 0.3) < 0.0001:
print("Approximately equal")
Why it happens: decimal fractions like 0.1 can't be stored exactly in binary floating point, so two mathematically equal expressions can differ by a tiny rounding error. Compare with a tolerance instead of ==, or use the decimal module for money.
# Bad
if value == None:
pass
# Good
if value is None:
pass
Why it happens: == works here purely by coincidence, so beginners reach for the operator they already know. is checks true object identity, which is what you actually mean when testing against the singleton None.
# Bad
age = input("Age: ")
if age > 18: # Error! Comparing string to number
# Good
age = int(input("Age: "))
if age > 18:
print("Adult")
Why it happens: input() always returns a string, even if the user types digits, and Python won't silently compare a string to a number the way some looser languages do — you'll get a TypeError instead of a guess.
# Bad
text = "hello"
text[0] = "H" # Error!
# Good
text = "H" + text[1:] # Create new string
Why it happens: in many languages a string is just a mutable array of characters, so developers instinctively try to edit one index. Python strings are immutable by design (partly so they can be safely hashed as dictionary keys), so you must build a new string instead.
11. Practice Exercises
Use these exercises to reinforce the ideas before moving on to functions and larger programs:
Swap the values of two variables without using a third variable.
a = 10
b = 20
# Your code here
# Hint: Python tuple unpacking (a, b = b, a) handles this for ANY
# data type. The classic "XOR swap trick" only works for integers
# and won't work here, so avoid reaching for it.
# Result: a = 20, b = 10
Create a program that takes any input and converts it to all possible types. Show which conversions work and which fail.
Write a program that analyzes a string and reports:
- Length
- Number of vowels
- Number of digits
- Number of spaces
- Is palindrome?
Create a grading system that:
- Accepts numeric grades (0-100)
- Converts to letter grade (A, B, C, D, F)
- Determines if student passed (≥60)
- Calculates GPA (4.0 scale)
Create validators for:
- Email format (must contain @ and .)
- Phone number (10 digits)
- Password (8+ chars, upper, lower, digit)
- Age (1-120)
12. Frequently Asked Questions
What is the difference between a variable and a data type in Python?
A variable is the name you choose to reference a value in memory (like age). A data type describes what kind of value that is (like int or str) and, crucially, what operations are valid on it.
What are Python's 5 basic data types?
The five fundamentals covered in this lesson are str (text), int (whole numbers), float (decimals), bool (True/False), and NoneType (absence of a value). Python also has sequence, mapping, and set types you'll meet in later lessons.
Why does 0.1 + 0.2 not equal 0.3 in Python?
Floats are stored in binary, and most decimal fractions — including 0.1 — can't be represented exactly in binary, the same way 1/3 can't be written exactly in decimal. Use abs(a - b) < tolerance for float comparisons, or the decimal module for exact decimal math.
Should I use == or is to check for None?
Use is None. None is a singleton — only one instance ever exists — so identity comparison is both the technically correct check and the community-standard convention enforced by linters like flake8.
Can I change a Python string after creating it?
No — strings are immutable. Every method like .upper() or .replace() returns a brand-new string rather than modifying the original one in place.
13. References & Further Reading
- Python Language Reference — Data Model (docs.python.org)
- Python Standard Library — Built-in Types (docs.python.org/3/library/stdtypes.html)
- Python Standard Library — decimal module (docs.python.org/3/library/decimal.html)
- Python Standard Library — math module (docs.python.org/3/library/math.html)
- PEP 8 — Style Guide for Python Code (peps.python.org/pep-0008)
- PEP 3101 — Advanced String Formatting / f-strings background (peps.python.org/pep-3101)
- What's New in Python — release notes by version (docs.python.org/3/whatsnew/)
This article is an independently written synthesis for teaching purposes. All explanations, analogies, and code examples were created for this post; the sources above were used only to verify technical accuracy, not copied from.
14. Summary
- Variables are names bound to values, created with
=, with no separate type declaration needed - Python is dynamically typed — a variable's type is inferred from its current value and can change on reassignment
- Integers have unlimited precision; floats trade some precision for the ability to represent fractions
- Strings are immutable sequences of characters — every "modifying" method returns a new string
- Booleans power every conditional; remember that empty/zero values are Falsy and everything else is Truthy
- None represents the deliberate absence of a value — always check it with
is None, never== - Type casting bridges data across boundaries (like
input()) that only speak strings — useint(),float(), andstr()deliberately, inside atry/exceptwhen the input isn't trusted - Use descriptive
snake_casenames, validate and convert user input immediately, and lean on the Student Management System project to see every concept working together
Master this foundation and everything else in Python — functions, loops, classes, even async code — clicks into place faster, because it's all just more sophisticated ways of organizing names and the values they point to. Keep coding, keep learning.
Comments
Post a Comment