Python Basics: Variables, Loops, Lists & Functions Explained Simply
Chapters: 0:00 Why Learn Python 0:18 Key Terms, Plain English 0:40 Variables, the Labeled Box 1:00 Data Types You Will See 1:22 Strings, Text You Can Slice 1:44 Lists, a Row of Boxes 2:00 If Statements, Making Choices 2:23 Loops, Doing Things Repeatedly 2:45 Functions, Reusable Recipes 3:06 Common Mistakes Beginners Make 3:31 Lists vs Tuples vs Dictionaries 3:54 Python vs Other Languages 4:18 Recap, What You Now Know Learn real Python fundamentals in plain English: variables as labeled boxes, key data types, string slicing, lists, if statements, loops, and functions as reusable recipes. We also cover common beginner mistakes, lists vs tuples vs dictionaries, and how Python compares to other languages. Perfect for absolute beginners starting to code. #python #pythonbasics #learntocode #coding #beginnerpython
Introduction
Every developer's Python journey starts in the same place: staring at a blinking cursor, wondering why anyone thought print("Hello, World!") was a reasonable first step. But here's the thing — Python earned its spot as the go-to first language for a good reason. It strips away the ceremony that languages like Java or C force on beginners and lets you focus on the actual logic of programming: storing values, making decisions, repeating work, and organizing code into reusable pieces.
This matters beyond just "learning to code" for its own sake. Every technical interview, every take-home assignment, and every production codebase you'll ever touch is built from these same five ideas: variables, data types, conditionals, loops, and functions. Interviewers rarely ask you to define a variable directly, but they absolutely test whether you understand how data moves through a program — and that understanding starts here. Skipping these fundamentals is like trying to learn a language without learning the alphabet; you might memorize a few phrases, but you'll never be able to construct a new sentence with confidence.
By the end of this article, you'll understand not just the syntax, but why Python is built the way it is — and you'll be ready to write small, real scripts of your own.
Problem Overview
The "problem" here isn't a single coding challenge — it's a conceptual gap. Beginners often learn Python syntax by copying examples without understanding what's actually happening underneath. They know x = 5 "works," but they can't explain what a variable really is, why lists start counting at zero, or why if statements care so much about indentation.
So instead of a LeetCode-style problem, think of this as reverse-engineering a mental model. We need to answer:
- What does it mean to "store" a value in Python?
- How does Python know the difference between text and numbers?
- How do you make a program choose between two paths?
- How do you avoid repeating the same line of code ten times?
- How do you package logic so you can reuse it without retyping it?
Once you have solid answers to these five questions, everything else in Python — classes, error handling, even machine learning libraries — sits on top of this same foundation.
Example
Let's ground each concept with a concrete example instead of abstract definitions.
age = 28
name = "Priya"
price = 19.99
is_available = True
Here, age holds a whole number, name holds text, price holds a decimal, and is_available holds a True/False value. Notice we never declared a type — Python figures it out from the value itself.
word = "hello"
print(word[0]) # h
word[0] returns h because Python indexes starting at position 0, not 1. This is called zero-based indexing, and it's one of the most common sources of beginner confusion.
lockers = [10, 20, 30]
print(lockers[1]) # 20
The list lockers is a sequence of values, each with a position number. lockers[1] gives you the second item, 20, because counting starts at 0.
temperature = 15
if temperature < 0:
print("Freezing")
else:
print("Not freezing")
This prints Not freezing because 15 is not less than 0, so Python skips the if block and runs the else block instead.
Intuition
Here's how an experienced engineer actually thinks about these concepts — not as rules to memorize, but as physical metaphors that make the syntax predictable.
Variables are labeled boxes. When you write age = 28, you're not creating "a number called age" in some abstract sense — you're sticking a label (age) onto a box that contains the value 28. The box can later hold a different value; the label is just how you refer to it. This mental model explains why age = 28 followed by age = 29 doesn't cause an error — you're just putting a new item in the same labeled box.
Types exist because operations mean different things for different data. 3 + 4 gives you 7. But "3" + "4" gives you "34" — string concatenation, not addition. Python needs to know the type of a value to know which behavior to use. This is also why "3" + 4 throws an error: Python won't guess whether you meant math or text-joining.
Strings and lists are both sequences, so they share the same indexing logic. Once you understand that word[0] gets the first character of a string, lockers[0] getting the first item of a list feels obvious — same rule, different container.
Indentation in if statements isn't cosmetic — it's structural. Python uses whitespace instead of curly braces to define which lines belong to which block. Once you see indentation as "this is inside that block" rather than "this looks tidy," you stop making the classic beginner mistake of misaligned code that silently changes behavior.
Loops exist to eliminate repetition. If you ever find yourself writing the same line five times with only a small change, that's the signal a loop belongs there. A for loop is for "do this to each item in a known collection." A while loop is for "keep doing this until some condition changes" — you don't always know in advance how many times it'll run.
Functions are for packaging logic you'll reuse. The moment you copy-paste a block of code into a second place in your script, that's the signal to wrap it in a function instead. It's the same instinct as writing a recipe card once instead of re-explaining the steps every time you cook the dish.
Once these mental models click, you stop memorizing syntax and start predicting it.
Brute Force Solution
There isn't a traditional "brute force vs optimal" split here since this isn't an algorithmic problem — but there is a beginner-vs-experienced-engineer split in how people write basic Python, which is worth calling out.
The brute force approach (common beginner pattern): writing everything inline with no functions, no reuse, and copy-pasted logic.
print("Add: ", 3 + 4)
print("Add: ", 10 + 20)
print("Add: ", 100 + 200)
Advantages: Works fine for tiny, one-off scripts. Zero abstraction to think about.
Disadvantages: As soon as the logic needs to change (say, adding logging, or handling negative numbers), you have to update it in every single place it was copy-pasted. This is the exact pattern that causes bugs to multiply — fix it in one spot, forget the other two.
Time and space complexity: Not meaningfully different from the optimal version for such small operations — the real cost here is maintenance, not runtime.
Optimal Solution
The "optimal" approach uses functions to eliminate repetition and variables/lists to organize state cleanly.
def add(a, b):
return a + b
print(add(3, 4))
print(add(10, 20))
print(add(100, 200))
Here's what changed conceptually:
| Beginner Pattern | Structured Pattern |
|---|---|
| Logic repeated inline | Logic defined once in a function |
| Hard to update | Update once, affects every call |
| No clear "unit" of behavior | add() is a clear, testable unit |
This same principle scales up: a list groups related data, a function groups related behavior, and an if/else block groups related decisions. Structuring code this way is what makes larger programs manageable.
Python Code
Here's a small, complete script that ties all five concepts together into one coherent program:
def describe_temperature(temperature):
"""Return a human-readable description of a temperature in Celsius."""
if temperature < 0:
return "Freezing"
elif temperature < 15:
return "Cold"
elif temperature < 25:
return "Mild"
else:
return "Hot"
def main():
readings = [-5, 10, 20, 30] # a list of temperature readings
for temperature in readings:
description = describe_temperature(temperature)
print(f"{temperature}°C is {description}")
if __name__ == "__main__":
main()
Code Walkthrough
def describe_temperature(temperature):defines a reusable function that takes one input,temperature.- The
if/elif/elsechain checks the value against ranges in order, top to bottom, and returns as soon as one condition isTrue. returnsends a value back to whoever called the function — it doesn't print anything itself.readings = [-5, 10, 20, 30]is a list holding four numbers, each accessible by position (readings[0]is-5).for temperature in readings:walks through the list one item at a time, temporarily assigning each value totemperature.- The f-string
f"{temperature}°C is {description}"embeds variable values directly into the printed text. if __name__ == "__main__":is a standard guard that runsmain()only when the file is executed directly, not when it's imported elsewhere.
Dry Run
Let's trace through readings = [-5, 10, 20, 30]:
temperature = -5→-5 < 0isTrue→ returns"Freezing"→ prints-5°C is Freezingtemperature = 10→-5 < 0isFalse,10 < 15isTrue→ returns"Cold"→ prints10°C is Coldtemperature = 20→ fails first two checks,20 < 25isTrue→ returns"Mild"→ prints20°C is Mildtemperature = 30→ fails all three checks → falls toelse→ returns"Hot"→ prints30°C is Hot
Complexity Analysis
- Time complexity: O(n), where n is the number of readings in the list. Each item is visited exactly once, and the
if/elifcheck inside is constant time (at most four comparisons regardless of list size). - Space complexity: O(1) additional space — we're not creating new data structures proportional to input size, just reusing a couple of variables per iteration.
These are correct because the loop touches every element exactly once (no nested loops over the same list) and the function itself doesn't allocate memory that grows with input.
Alternative Solutions
You could replace the if/elif chain with a dictionary lookup for fixed categories, but since our conditions depend on ranges rather than exact values, a dictionary doesn't map cleanly here — dictionaries are ideal for exact-key lookups (like mapping a country code to a country name), not range checks. The if/elif structure is the right tool for this specific job.
Edge Cases
- Empty list:
readings = []— theforloop simply doesn't execute, and nothing prints. No error is thrown. - Boundary values:
temperature = 0— falls into theelif temperature < 15branch, not "Freezing," since0 < 0isFalse. Always double-check boundary behavior in range-based conditions. - Negative extreme values:
temperature = -100still correctly returns"Freezing"since it's still less than 0. - Non-numeric input: Passing a string like
"cold"intodescribe_temperaturewould raise aTypeErroron the comparison — Python won't silently convert types for you. - Duplicate values in the list:
[10, 10, 10]is handled identically each time — loops don't care about duplicates, they just process what's there.
Common Mistakes
- Using
=instead of==.if temperature = 0:is a syntax error —=assigns,==compares. - Forgetting quotes around strings. Writing
name = Priyainstead ofname = "Priya"makes Python thinkPriyais a variable name, which causes aNameError. - Misaligned indentation. Mixing tabs and spaces, or indenting inconsistently, breaks the logical grouping of
if/for/defblocks. - Off-by-one errors in loops. Assuming a list of length
nhas valid indices up toninstead ofn - 1causes anIndexError. - Trying to modify a tuple. Since tuples are immutable,
my_tuple[0] = 5raises aTypeError— use a list if you need to change values later. - Confusing
eliforder. Placing a broader condition before a narrower one (e.g., checkingtemperature < 100beforetemperature < 0) means the narrower branch never executes.
Interview Questions
- What's the difference between a list, a tuple, and a dictionary, and when would you choose each?
- Why does Python use indentation instead of braces, and what problems can that cause?
- What happens if you try to access an index that doesn't exist in a list?
- How does Python decide the type of a variable if you never declare it?
- What's the difference between a
forloop and awhileloop, and when is each more appropriate?
Similar Problems
- FizzBuzz — reinforces loops and conditionals together, a classic first interview screening question.
- Reverse a String — builds on string indexing and slicing fundamentals covered here.
- Two Sum — the natural next step once you're comfortable with lists and functions, introducing dictionaries for fast lookups.
- Valid Parentheses — extends conditional logic and loops into stack-based thinking.
Key Takeaways
- Variables are labels on values, not containers with fixed types.
- Every value has a type, and types determine which operations are valid.
- Indexing starts at zero — internalize this early to avoid constant off-by-one confusion.
- Indentation in Python is functional, not stylistic — it defines code blocks.
- Loops eliminate repetition; functions eliminate duplicated logic.
- Choosing between lists, tuples, and dictionaries comes down to whether data changes, needs to stay fixed, or needs to be looked up by name.
Watch the Video
If you'd rather see these concepts explained visually with live code, watch the full walkthrough here: {LINK}
About the Series
This article is part of the Daily Python & LeetCode series, where we break down one Python concept or coding problem each day — from absolute fundamentals like this one to full interview-style algorithm problems. The goal is simple: build real understanding, one small lesson at a time, instead of cramming syntax the night before an interview.
Call To Action
If this helped clarify Python fundamentals, subscribe on YouTube for daily walkthroughs, and subscribe to the Substack newsletter for the written breakdowns delivered straight to your inbox. Drop a comment with which concept you'd like explained next, and share this with anyone just starting their coding journey.
The solution
for fruit in ["apple", "pear"]:
print(fruit)
n = 0
while n < 3:
n += 1Ready to try it yourself? Solve General problems with instant feedback in the practice sandbox.
Practice now →


