Appendix D: FAQ and Troubleshooting
This appendix collects the questions students ask most frequently, organized by the chapter where the topic is introduced. If you're stuck, find the section closest to your current chapter and look for your symptom.
D.1 General Python Questions
"What's the difference between = and ==?" (Ch. 3-4)
= is the assignment operator. It gives a name to a value:
x = 5 # "x now refers to the value 5"
== is the comparison operator. It tests whether two values are equal and returns True or False:
x == 5 # "is x equal to 5?" → True
x == 10 # "is x equal to 10?" → False
Using = when you mean == is one of the most common beginner bugs:
if grade = "A": # SyntaxError! Should be ==
print("Great!")
Python catches this one as a SyntaxError, so you'll know right away. Some other languages don't catch it, making it a silent logic error — Python's design is protecting you here.
"What's the difference between print() and return?" (Ch. 6)
print() displays text to the screen. It's for humans to read. The function still returns None.
return sends a value back to the code that called the function. The value can be stored, used in calculations, or passed to another function.
def add_print(a, b):
print(a + b) # displays the result, returns None
def add_return(a, b):
return a + b # sends the result back to the caller
result1 = add_print(3, 4) # prints 7, result1 is None
result2 = add_return(3, 4) # prints nothing, result2 is 7
Rule of thumb: if you need to use the result of a function in further computation, use return. If you just need to display something to the user, use print(). Most functions should use return; print() belongs in the main flow of the program, not buried inside utility functions.
"When do I use for vs. while?" (Ch. 5)
Use for when you know how many times to loop (or you're iterating over a collection):
for i in range(10): # exactly 10 times
for name in student_names: # once per student
for char in message: # once per character
Use while when you don't know how many times you'll loop — you just know the condition for stopping:
while user_input != "quit": # until user says quit
while balance > 0: # until money runs out
while not is_valid(data): # until data passes validation
"Why does input() always return a string?" (Ch. 2-3)
Because Python can't read your mind. If the user types 42, should Python interpret that as the integer 42, the float 42.0, or the string "42"? Python plays it safe and always returns a string. You convert when needed:
age = int(input("Your age: ")) # convert to int
price = float(input("Price: ")) # convert to float
name = input("Your name: ") # already a string — no conversion needed
"What does None mean?" (Ch. 6)
None is Python's way of saying "nothing" or "no value." It's the return value of functions that don't explicitly return anything:
def say_hello():
print("Hello!") # no return statement
result = say_hello() # result is None
None is not the same as 0, "", [], or False. It's a distinct value meaning "absence of a value."
D.2 Syntax Errors
"Why does my code give a SyntaxError?" (Ch. 2)
A SyntaxError means Python couldn't understand your code's structure. It's like a grammatical error in English — the words might be real, but the sentence doesn't make sense. Common causes:
Missing or mismatched quotes:
print("Hello, World!) # missing closing "
print('It's a test') # apostrophe ends the string early
# Fix: print("It's a test") or print('It\'s a test')
Missing colon after if, for, while, def, class:
if x > 5 # missing :
print("big")
# Fix: if x > 5:
Mismatched parentheses or brackets:
print("Hello" # missing closing )
my_list = [1, 2, 3 # missing closing ]
Using = instead of == in a condition:
if x = 5: # should be ==
Indentation problems:
def greet():
print("Hello") # not indented
# Fix: indent the body of the function
Pro tip: Python reports the error on the line where it noticed the problem, which isn't always where the bug is. If the line Python highlights looks fine, check the line above it — often the real error is an unclosed quote, parenthesis, or bracket on the previous line.
"Why does Python say 'unexpected indent'?" (Ch. 2)
Python uses indentation to define code blocks (unlike languages that use braces {}). You'll get this error if:
-
You indented a line that shouldn't be indented:
python x = 5 print(x) # IndentationError — this line shouldn't be indented -
You mixed tabs and spaces (invisible but Python treats them differently): - Fix: configure your editor to insert spaces when you press Tab (VS Code does this by default).
-
You forgot to un-indent after a block ends:
python if True: print("A") print("B") print("C") # is this inside the if or not? Indentation decides.
D.3 Runtime Errors
"TypeError: can only concatenate str (not 'int') to str" (Ch. 3)
You tried to add (+) a string and a number without converting:
age = 25
print("Age: " + age) # TypeError
# Fix 1: convert to string
print("Age: " + str(age))
# Fix 2: use f-string (preferred)
print(f"Age: {age}")
"ValueError: invalid literal for int() with base 10" (Ch. 3)
You tried to convert something to int() that isn't a valid integer:
int("hello") # ValueError
int("3.14") # ValueError — use float() first, then int()
int("") # ValueError — empty string
int(input("Number: ")) # ValueError if user types "abc"
Fix: validate input before converting, or use try/except (Ch. 11):
try:
n = int(input("Number: "))
except ValueError:
print("That's not a valid number.")
"NameError: name 'variable' is not defined" (Ch. 3)
You used a variable name that Python doesn't know about. Causes:
- Typo: You wrote
pritninstead ofprint, ormesageinstead ofmessage. - Using before defining: You referenced a variable before assigning it a value.
- Scope issue: The variable exists inside a function but you're trying to use it outside (Ch. 6).
- Forgot to import: You used
math.sqrt()withoutimport math.
"IndexError: list index out of range" (Ch. 8)
You tried to access a list position that doesn't exist:
items = ["a", "b", "c"] # valid indices: 0, 1, 2 (or -1, -2, -3)
print(items[3]) # IndexError — only 3 items, max index is 2
print(items[len(items)]) # IndexError — same problem (off by one)
# Fix:
print(items[len(items) - 1]) # last item
print(items[-1]) # better: last item
This is the dreaded "off-by-one error." Remember: indices start at 0, so a list of length n has valid indices 0 through n-1.
"KeyError" (Ch. 9)
You tried to access a dictionary key that doesn't exist:
person = {"name": "Alice", "age": 30}
print(person["email"]) # KeyError: 'email'
# Fix 1: check first
if "email" in person:
print(person["email"])
# Fix 2: use .get() with a default
print(person.get("email", "N/A"))
"FileNotFoundError" (Ch. 10)
Python can't find the file you're trying to open. Causes:
- Wrong filename: Check spelling and extension (
data.txtvsdata.csv). - Wrong directory: The file exists, but your script is running from a different folder. Use
print(os.getcwd())to see where Python thinks you are. - Wrong path separator (Windows): Use raw strings or forward slashes: ```python # These all work on Windows: open(r"C:\Users\data\file.txt") open("C:/Users/data/file.txt") from pathlib import Path open(Path("C:/Users/data/file.txt"))
# This breaks (backslash escapes):
open("C:\Users\data\file.txt") # \U and \f are escape sequences!
``
4. **Relative path confusion:**open("data.txt")looks in the *current working directory*, not necessarily the directory where your script is. See Ch. 10 for usingPath(file).parent`.
D.4 Logic Errors ("My Code Runs but Gives Wrong Results")
Logic errors are the hardest to find because Python doesn't tell you anything is wrong — the program runs without errors but produces incorrect output.
Step-by-Step Debugging Strategy (Ch. 13)
-
Add print statements at key points to see the actual values:
python def calculate_grade(scores, weights): total = 0 for i in range(len(scores)): print(f" DEBUG: score={scores[i]}, weight={weights[i]}, product={scores[i] * weights[i]}") total += scores[i] * weights[i] print(f" DEBUG: total={total}") return total -
Test with simple inputs where you know the expected answer. If
calculate_average([10, 20, 30])doesn't return20, you have a bug. -
Binary search for the bug. Comment out half the code. Does the first half produce correct intermediate results? If yes, the bug is in the second half. Keep halving until you find the problem.
-
Rubber duck debugging. Explain your code line by line to an inanimate object (or a patient friend). The act of articulating your logic often reveals the flaw.
Common Logic Errors
Off-by-one errors (Ch. 5):
# Prints 0-9, not 1-10
for i in range(10):
print(i)
# Fix: range(1, 11) for 1-10
Wrong operator precedence (Ch. 3):
# Bug: divides num2 by 2 first, then adds to num1
average = num1 + num2 / 2
# Fix: add first, then divide
average = (num1 + num2) / 2
Percentage calculations (Ch. 3):
# Bug: 85 * 40 = 3400, not a weighted percentage
weighted = homework * 40 + midterm * 30 + final * 30
# Fix: use decimal weights
weighted = homework * 0.40 + midterm * 0.30 + final * 0.30
Comparing floating-point numbers (Ch. 3):
# Bug: may be False due to floating-point imprecision
0.1 + 0.2 == 0.3 # False!
# Fix: compare with tolerance
abs((0.1 + 0.2) - 0.3) < 1e-9 # True
Returning inside a loop (Ch. 6):
# Bug: returns after checking only the first item
def sum_positives(numbers):
total = 0
for num in numbers:
if num > 0:
total += num
return total # should be outside the loop!
return total
D.5 Loop Problems
"Why is my loop infinite?" (Ch. 5)
An infinite loop happens when the loop condition never becomes false. Common causes:
Forgot to update the loop variable:
count = 0
while count < 10:
print(count)
# Bug: count never changes! Loop runs forever.
# Fix: add count += 1 inside the loop
Updating the wrong variable:
i = 0
while i < 10:
print(i)
j += 1 # Bug: incrementing j, not i
Condition can never be false:
x = 5
while x > 0:
print(x)
x += 1 # Bug: x gets bigger, not smaller
How to stop an infinite loop:
- Press Ctrl+C in the terminal.
- In VS Code, click the trash can icon in the terminal panel.
"My loop skips the last item" (Ch. 5)
This is usually a range() issue. range(n) generates 0 through n-1, not 0 through n:
items = ["a", "b", "c", "d"]
for i in range(len(items) - 1): # Bug: misses "d"
print(items[i])
# Fix: range(len(items)) or better: for item in items:
D.6 Mutable Data Pitfalls
"Why does changing one list change another?" (Ch. 8)
This is the aliasing problem — one of the most common sources of bugs for intermediate students.
When you write b = a for a list, you don't create a copy. Both a and b refer to the same list object in memory. Changes through one name are visible through the other:
a = [1, 2, 3]
b = a # b points to the SAME list
b.append(4)
print(a) # [1, 2, 3, 4] — a changed too!
Fixes:
b = a.copy() # shallow copy — independent list
b = a[:] # slicing copy — same effect
b = list(a) # constructor copy — same effect
# For nested lists, use deepcopy:
import copy
b = copy.deepcopy(a)
"My default argument is accumulating values across calls" (Ch. 6)
Never use a mutable default argument:
# Bug: the default list is shared across all calls
def add_item(item, items=[]):
items.append(item)
return items
add_item("a") # ['a']
add_item("b") # ['a', 'b'] — 'a' is still there!
Fix: Use None as the default and create a new list inside:
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
D.7 Import and Module Problems
"ModuleNotFoundError: No module named '...'" (Ch. 12)
Cause 1: The module isn't installed. Third-party packages must be installed with pip:
python3 -m pip install requests
Cause 2: Different Python installation. The pip that installed the package and the python running your script are different. Fix by using:
python3 -m pip install requests
python3 my_script.py
Cause 3: Virtual environment not activated. If you installed the package in a virtual environment, activate it first (see Appendix B).
Cause 4: File name collision. If your script is named random.py, csv.py, json.py, or any other standard library module name, Python imports your file instead of the standard library. Rename your file.
Cause 5: Missing __init__.py. If you created a package (directory with modules), it needs an __init__.py file (can be empty) in Python versions before 3.3, and it's still good practice.
"ImportError: cannot import name '...' from '...'" (Ch. 12)
The module exists but doesn't have the name you're trying to import. Common causes: - Typo in the function/class name. - Wrong version of the library (the function was added in a later version). - Circular import: module A imports from module B, which imports from module A.
D.8 Object-Oriented Programming Questions
"What does self do?" (Ch. 14)
self is a reference to the current instance of the class. It's how an object refers to its own data and methods. When you call dog.bark(), Python translates it to Dog.bark(dog) — the object itself gets passed as the first argument.
You must include self as the first parameter of every instance method, and you use self.attribute to access the object's data:
class Dog:
def __init__(self, name):
self.name = name # self.name is an attribute of THIS dog
def bark(self):
return f"{self.name} says Woof!"
fido = Dog("Fido")
fido.bark() # "Fido says Woof!"
Forgetting self is the single most common OOP bug for beginners:
class Dog:
def __init__(self, name):
name = name # Bug! This creates a local variable, not an attribute
# Fix: self.name = name
"Why do I get 'takes 0 positional arguments but 1 was given'?" (Ch. 14)
You forgot self in a method definition:
class Dog:
def bark(): # Bug: missing self
return "Woof!"
fido = Dog()
fido.bark() # TypeError: bark() takes 0 positional arguments but 1 was given
# Fix: def bark(self):
D.9 Platform-Specific Issues
Windows
- Path separators: Use forward slashes (
/) or raw strings (r"C:\Users\...") in file paths. Backslashes are escape characters in Python strings. pythonvspython3vspy: Windows installations are inconsistent. Try all three and use whichever works. Thepylauncher is the most reliable on Windows.- PowerShell script execution policy: If
venv\Scripts\Activate.ps1fails, see Appendix B for the fix. - Line endings: Windows uses
\r\n(CRLF), while macOS/Linux use\n(LF). This usually doesn't matter, but if you see\rcharacters in your output, open the file in VS Code and change the line ending setting (shown in the bottom status bar).
macOS
- Use
python3, notpython: The barepythoncommand may not exist or may point to Python 2. - Xcode Command Line Tools: Some packages require C compilation. If installation fails, run
xcode-select --install. - Gatekeeper warnings: If macOS says "Python can't be opened because it is from an unidentified developer," go to System Preferences > Security & Privacy and click "Open Anyway."
- Homebrew vs system Python: Homebrew Python and the python.org installer are separate installations. Be consistent — use one or the other.
Linux
- Use your package manager:
sudo apt install python3-xyz(Debian/Ubuntu) orsudo dnf install python3-xyz(Fedora) for system packages. venvmodule missing: Some distros don't include it by default. Install it:sudo apt install python3.12-venv.- Permission errors with pip: Never use
sudo pip install. Use a virtual environment instead, orpip install --user. - Multiple Python versions: Use
python3.12explicitly if you have several versions installed. Useupdate-alternativesto set defaults (see Appendix B).
D.10 Quick Diagnostic Checklist
When you're stuck, work through this checklist:
-
Read the error message. Python tells you the file, line number, and error type. Read the last line of the traceback first.
-
Check the line above. If the reported line looks correct, the bug is often on the line above (unclosed quote, paren, or bracket).
-
Check variable names. Are you using the exact same name you defined? Python is case-sensitive:
Nameandnameare different variables. -
Check types. Use
type(variable)to verify. Is it a string when you expected an integer? Didinput()give you a string that you forgot to convert? -
Check indentation. Is your code inside the block you think it's in? Add a print statement at the same indentation level to verify.
-
Simplify. Remove everything except the core logic. Does the simplified version work? Add pieces back one at a time until it breaks.
-
Search the error message. Copy the last line of the traceback, paste it into a search engine. Someone has had this exact problem before.
-
Take a break. Seriously. Walk away for 10 minutes. The answer often appears when you stop staring at the screen.
Most errors you'll encounter in this course have been encountered by thousands of students before you. The error message is not your enemy — it's Python trying to help you. Read it carefully.