10xdev Book: Programming from Zero to Pro with Python

Chapter 4: Variables and Core Data Types in Modern Python

Chapter Introduction

In the last chapter, you learned the basic syntax and how to get data in and out of your Python 3.14 programs using input() and print(). We saw that input() always gives us text, even if the user types numbers. This highlights a crucial concept: Python needs to know the type of data it’s working with.

This chapter dives deep into variables – the named containers for your data – and the fundamental data types they hold: text, numbers, and logical values. Understanding these is essential for writing code that works correctly.


1. Variables: Naming Your Data

As a quick recap, variables are names you assign to values stored in the computer’s memory. You create them using the assignment operator (=).

# snake_case is the preferred style
user_name: str = "Alice"
item_count: int = 5
unit_price: float = 29.95
is_active: bool = True

Key Points:

  • Variables are references (labels) pointing to data in memory, not the data itself.
  • Use descriptive snake_case names.
  • They are case-sensitive.

2. Core Data Types

Python needs to know if it’s dealing with text, whole numbers, decimals, or logical states. These are the built-in primitive types:

A. Text (Strings - str)

Strings represent sequences of characters, enclosed in single (') or double (") quotes.

  • Concatenation: Use + to join strings.
    greeting = "Hello"
    name = "Bob"
    message = greeting + ", " + name + "!" # -> "Hello, Bob!"
    print(message)
    
  • Indexing & Slicing: Access individual characters (starting at index 0) or ranges.
    word = "Python"
    print(word[0])    # -> 'P'
    print(word[-1])   # -> 'n' (last character)
    print(word[1:4])  # -> 'yth' (index 1 up to, not including, 4)
    print(word[:3])   # -> 'Pyt' (from start up to index 3)
    print(word[3:])   # -> 'hon' (from index 3 to end)
    
  • Common Methods: Strings have built-in functions (methods).
    text = "  Some Data!  "
    print(text.strip())      # -> "Some Data!" (remove leading/trailing whitespace)
    print(text.lower())      # -> "  some data!  "
    print(text.upper())      # -> "  SOME DATA!  "
    print(text.strip().replace("!", ".")) # -> "Some Data."
    print("comma,separated,values".split(',')) # -> ['comma', 'separated', 'values']
    
  • Length: Use the len() function.
    print(len("Python")) # -> 6
    
  • Escape Sequences: Use backslash \ for special characters like newline (\n) or tab (\t).
    print("Line 1\nLine 2\tIndented")
    
  • F-Strings (Formatted String Literals): The best way to embed variables.
    age = 30
    print(f"User {name} is {age} years old.") # Clean and readable!
    print(f"Price: ${unit_price:.2f}")      # Format float to 2 decimal places
    
  • (Python 3.14+) T-Strings: While f-strings evaluate immediately, Python 3.14 introduced template strings (t-strings) prefixed with t. They return a special Template object, allowing you to inspect or process the parts before creating the final string. This is powerful for tasks like safely generating HTML or SQL by sanitizing inputs. F-strings are still perfect for everyday formatting, but t-strings offer more control for complex or security-sensitive cases.
    # Example showing the concept (more details in later chapters or specific use cases)
    # import html
    # user_input = "<script>alert('XSS')</script>"
    # safe_template = t"<div>{user_input}</div>"
    # Processed later: rendered_html = build_template_processed(safe_template, html.escape)
    

B. Numbers (int, float)

  • Integers (int): Whole numbers (e.g., -10, 0, 42).
  • Floats (float): Numbers with a decimal point (e.g., 3.14, -0.5, 10.0).
  • Operations: All standard math operators work as expected. Division / always produces a float. Use // for integer division (discarding the remainder).
  • Readability: Use underscores _ in long numbers. Python ignores them.
    large_number = 1_000_000_000 # Much easier to read than 1000000000
    print(large_number)
    

C. Booleans (bool)

  • Represent logical states: True or False (must be capitalized!).
  • Result from comparisons (>, <, ==, !=) and logical operators (and, or, not).
  • Essential for controlling program flow with if statements (Chapter 5).
is_cold = unit_price < 0
print(f"Is the price negative? {is_cold}") # -> False

can_proceed = is_active and item_count > 0
print(f"Can we proceed? {can_proceed}") # -> True

3. Type Hints (Modern Python Practice)

While Python is dynamically typed (you don’t have to declare types), adding type hints is a modern best practice. They act like documentation, improve code readability, and help tools like linters and type checkers find potential bugs before you run the code.

player_name: str = "Gandalf"
level: int = 99
mana_percent: float = 95.5
is_wizard: bool = True

# For functions:
def greet(name: str) -> str:
    return f"Greetings, {name}!"

Note: Type hints do not change how Python runs your code by default; they are primarily for developers and tools.


4. (Python 3.14+) No More Quoted Forward References!

A common annoyance in older Python versions involved type hints. If a class method needed to hint at the class itself, but the class wasn’t fully defined yet, you had to put the type name in quotes (a “forward reference”).

# The OLD way (Python < 3.14, or without PEP 649 effects)
class Node:
    def set_next(self, node: "Node") -> "Node": # Quotes needed
        self.next_node = node
        return self

Thanks to deferred evaluation of annotations (PEP 649) being fully integrated and essentially default behavior now, Python 3.14+ is smarter. It doesn’t evaluate the hint immediately, avoiding the error. You can write the clean, intuitive version:

# The NEW, CLEAN way (Python 3.14+)
class Node:
    next_node: 'Node | None' # Still might need quotes for complex types or older checkers

    # But for simple self-references in method signatures, it often just works:
    def set_next(self, node: Node) -> Node: # No quotes needed here!
        self.next_node = node
        return self

This makes defining related classes and methods much cleaner.


5. Type Casting: Solving the input() Problem

Let’s revisit the input() function giving us text. To perform math, we must convert (cast) the string using int() or float().

quantity_str: str = input("Enter quantity: ")
price_str: str = input("Enter price per item: $")

try:
    quantity: int = int(quantity_str)
    price: float = float(price_str)
    total_cost: float = quantity * price
    print(f"Total cost: ${total_cost:.2f}")
except ValueError:
    print("Error: Please enter valid numbers for quantity and price.")

6. Checking a Variable’s Type (type())

Sometimes, especially when debugging, you need to know the actual data type stored in a variable. Use the built-in type() function.

value_a = 42
value_b = "42"

print(f"value_a is type: {type(value_a)}") # -> <class 'int'>
print(f"value_b is type: {type(value_b)}") # -> <class 'str'>

7. Practice Exercises

(These are adapted from the original Chapter 4 exercises, with type hints added for modern practice.)


Exercise 1: Simple Info Card

Task: Create variables (with type hints) for your name (str), age (int), and height in meters (float). Print them in a single sentence using an f-string.

Solution:

my_name: str = "Ali"
my_age: int = 28
my_height: float = 1.78

print(f"My name is {my_name}, I am {my_age} years old, and I am {my_height} meters tall.")

Exercise 2: Name Cleaner

Task: Ask the user for their first name (it might have extra spaces/weird casing). Clean it using .strip() and .title() and print the result.

Solution:

messy_name: str = input("Please enter your first name: ")
clean_name: str = messy_name.strip().title()
print(f"Your formatted name is: {clean_name}")

Exercise 3: Age Calculator

Task: Ask the user for their birth year. Calculate and print their approximate age (assume current year is 2025). Handle potential ValueError if they don’t enter a number.

Solution:

birth_year_str: str = input("What year were you born? ")
current_year: int = 2025

try:
    birth_year_int: int = int(birth_year_str)
    age: int = current_year - birth_year_int
    print(f"You are approximately {age} years old.")
except ValueError:
    print("Error: Please enter a valid year using numbers.")

Exercise 4: Price with Tax Calculator

Task: Ask for an item price. Add 15% tax (multiply by 1.15) and print the final price, formatted to 2 decimal places. Handle potential ValueError.

Solution:

original_price_str: str = input("Enter the item price: $")
TAX_RATE: float = 0.15 # Use a constant for the tax rate

try:
    original_price: float = float(original_price_str)
    final_price: float = original_price * (1 + TAX_RATE)
    print(f"The final price, including {TAX_RATE:.0%} tax, is: ${final_price:.2f}")
except ValueError:
    print("Error: Please enter a valid price.")


Exercise 5: Data Type Checker

Task: Create variables of type str, int, float, and bool. Print the type of each using type().

Solution:

book_title: str = "Intro to Python 3.14"
page_count: int = 150
book_price: float = 89.99
is_available: bool = True

print(f"'book_title' is type: {type(book_title)}")
print(f"'page_count' is type: {type(page_count)}")
print(f"'book_price' is type: {type(book_price)}")
print(f"'is_available' is type: {type(is_available)}")

Exercise 6: Word Repeater

Task: Ask for a word and a number. Print the word repeated that many times. Handle potential ValueError for the number.

Solution:

word: str = input("Enter a word to repeat: ")
repeat_count_str: str = input("How many times to repeat it? ")

try:
    repeat_count: int = int(repeat_count_str)
    if repeat_count < 0:
        print("Error: Repetition count cannot be negative.")
    else:
        repeated_word: str = word * repeat_count
        print(repeated_word)
except ValueError:
    print("Error: Please enter a whole number for the repetition count.")


Exercise 7: Boolean Comparison

Task: Ask for two numbers. Check if they are equal and print the boolean result (True or False). Handle potential ValueError.

Solution:

num1_str: str = input("Enter the first number: ")
num2_str: str = input("Enter the second number: ")

try:
    num1: float = float(num1_str)
    num2: float = float(num2_str)
    are_equal: bool = (num1 == num2)
    print(f"Are the two numbers equal? {are_equal}")
except ValueError:
    print("Error: Please enter valid numbers.")


Exercise 8: Username Generator

Task: Ask for first and last names. Create a username: first 3 letters of the first name (lowercase) + entire last name (lowercase).

Solution:

first_name: str = input("Enter your first name: ")
last_name: str = input("Enter your last name: ")

# Ensure names are not empty before slicing
if len(first_name) >= 3 and last_name:
    first_part: str = first_name[:3].lower()
    last_part: str = last_name.lower()
    username: str = first_part + last_part
    print(f"Your suggested username is: {username}")
else:
    print("Error: Please enter valid first (at least 3 chars) and last names.")


Exercise 9: Circle Circumference Calculator

Task: Ask for a circle’s radius. Calculate and print its circumference ($C = 2 \times \pi \times r$). Use 3.14159 for $\pi$. Handle potential ValueError.

Solution:

import math # Use math.pi for better precision

radius_str: str = input("Enter the radius of the circle: ")
PI_VALUE: float = math.pi # Use the more precise value from the math module

try:
    radius: float = float(radius_str)
    if radius < 0:
        print("Error: Radius cannot be negative.")
    else:
        circumference: float = 2 * PI_VALUE * radius
        print(f"The circumference is: {circumference:.2f}")
except ValueError:
    print("Error: Please enter a valid number for the radius.")


Exercise 10: Trip Itinerary Summary

Task: Ask for destination city (str), number of days (int), and total budget (float). Calculate the average daily spending budget and print a formatted summary. Handle potential ValueErrors.

Solution:

destination_city: str = input("What is your destination city? ").strip().title()
trip_days_str: str = input(f"How many days will you be in {destination_city}? ")
total_budget_str: str = input("What is your total budget for the trip? $")

try:
    trip_days: int = int(trip_days_str)
    total_budget: float = float(total_budget_str)

    if trip_days <= 0 or total_budget < 0:
        print("Error: Days must be positive, and budget cannot be negative.")
    else:
        daily_spending_avg: float = total_budget / trip_days
        print("\n--- Your Trip Summary ---")
        print(f"Destination: {destination_city}")
        print(f"Duration: {trip_days} days")
        print(f"Total Budget: ${total_budget:.2f}")
        print(f"Allowed Average Daily Spending: ${daily_spending_avg:.2f}")

except ValueError:
    print("\nError: Please enter valid numbers for days and budget.")


8. Chapter Summary

  • Variables are named references to data. Use snake_case.
  • Core data types are str (text), int (whole numbers), float (decimals), and bool (True/False).
  • F-strings are the preferred way to format strings. T-strings (Python 3.14+) offer more control for advanced templating.
  • Type hints (var: type) improve code clarity and help tools.
  • Python 3.14+ simplifies type hints by handling forward references automatically in many cases.
  • Type casting (int(), float(), str()) is essential for converting data, especially from input().
  • Use type() to check a variable’s type during debugging.

Storing data is essential, but the real power comes from making decisions based on that data. Next, we’ll teach your Python 3.14 programs how to control their flow using conditions (if/else) and loops (for/while).