Python Basics Complete Notes (1)
Python Basics Complete Notes (1)
Note: str() around input() is redundant since input() already returns a string.
f-strings
The letter f before a string tells Python to evaluate whatever is inside curly braces {} instead of treating it as
plain text.
name = "Ali"
print(f"My name is {name}") # My name is Ali
print("My name is {name}") # My name is {name} (no f, prints literally)
2. Type Conversion
The + operator behaves differently based on type: for strings it concatenates (joins text), for numbers it adds.
num_1 = input("Enter first number ")
num_2 = input("Enter second number ")
print(num_1 + num_2) # "5" + "3" = "53" (string joining, NOT math)
3. Arithmetic Operators
Operator Meaning Example (10, 3)
+ Addition 13
- Subtraction 7
* Multiplication 30
% Modulus (remainder) 1
Note: % (modulus) is used constantly for even/odd checks: if num % 2 == 0: means even.
4. Comparison and Logical Operators
>= <= > < == != # comparison operators
age = 20
if age >= 18 and age <= 60:
print("Working age")
if age < 18 or age > 60:
print("Outside working age")
Note: With elif, you don't need upper-bound checks (like marks<90) because Python only reaches an elif if all above
it were False.
8. Loops — while and for
while loop
Repeats code AS LONG AS a condition stays True.
count = 1
while count <= 5:
print(count)
count += 1
# Output: 1 2 3 4 5
Note: If you forget to update the loop variable (count += 1), the condition never becomes False -> INFINITE LOOP.
for i in range(5):
if i == 2:
continue # skips just this one iteration
print(i)
# Output: 0 1 3 4
# Output:
# 1 1
# 1 2
# 2 1
# 2 2
# 3 1
# 3 2
Note: i stays FROZEN for the entire inner loop. It only changes after ALL j-values are used up.
# CORRECT
for i in range(1,6):
for j in range(1,5):
print(j)
STEP 4 - VERIFY: Plug in each i value and confirm it matches the pattern.
Step 1: counts are 1,2,3,4 for i=1,2,3,4. Step 2: count = i (identical, no extra number needed). Step 3: range(1,
i+1). Step 4: verified correct for every row.
for i in range(1, 5):
for j in range(1, i + 1):
print(j, end=" ")
print()
Step 1: counts are 5,4,3,2,1. Step 2: count goes down by 1 as i goes up -> count = k - i. Test i=1: 5 = k-1 ->
k=6, so count = 6-i. Step 3: range(1, 7-i). Step 4: verified.
for i in range(1, 6):
for j in range(1, 7 - i):
print('*', end=" ")
print()
Step 1: counts are 2,4,6. Step 2: count doubles i -> count = 2*i. Step 3: range(1, 1+2*i). Step 4: verified (2,4,6
match).
for i in range(1, 4):
for j in range(1, 1 + 2*i):
print('*', end=" ")
print()
Note: There is no single universal formula for 'what to print' - it requires reading the actual numbers in the pattern
each time, unlike the range formula which is always fixed.
11. Lists
A list stores MULTIPLE values together in one variable, instead of separate variables for each value.
fruit1 = "apple" # messy - one variable per value
fruit2 = "banana"
fruits = ["apple", "banana", "mango"] # clean - one list holds all values
print(colors[0]) # red
print(colors[1]) # green
print(colors[-1]) # yellow (negative index = counts from the end)
print(len(colors)) # 4 (total number of items)
Note: colors[4] would crash - only indexes 0,1,2,3 exist in a 4-item list.
Modifying a list
fruits = ["apple", "banana"]
Note: append() adds to the end ONLY. insert(i, x) lets you choose the position. remove(x) deletes by value (crashes
if value not found). pop(i) deletes by index and RETURNS the removed item.
removed_item = [Link](0)
print(removed_item) # shows the actual value that was removed
print(fruits) # shows the list AFTER removal
for fruit in fruits: # gives you each VALUE directly, no range() needed
print(fruit)
for i in range(len(fruits)): # gives you the INDEX, use fruits[i] to get the value
print(f"Index {i}: {fruits[i]}")
Note: Use 'for item in list' when you only need the values. Use 'for i in range(len(list))' when you also need the
position/index.
if found:
print("Found")
else:
print("Not found")
Note: The 'found' flag survives after the loop ends, so you can check whether anything ever matched, even though
the loop itself is temporary.
Note: 'in' does exactly what the manual loop+flag does, but Python handles it internally in one line.
total = 0
for i in numbers:
total += i
print(total) # 146
Note: Built-in shortcuts exist too: sum(numbers), min(numbers), max(numbers) - we learned the manual version first
so you understand the mechanism underneath.
12. Dictionaries
A list stores items in ORDER, accessed by position. A dictionary stores items as KEY-VALUE pairs, accessed
by a name (key), not a position number.
student = {"name": "Attaullah", "age": 20, "city": "Swat"}
Accessing values
print(student["name"]) # Attaullah
print(student["age"]) # 20
# student["email"] would CRASH - key doesn't exist
Note: .get() never crashes even if the key is missing - safer than [ ] when you're not sure a key exists.
Note: Same syntax for add vs update - Python decides based on whether the key already exists.
Removing a key
del student["city"] # removes the key-value pair entirely
for key, value in [Link](): # gives you BOTH key and value together
print(f"{key}: {value}")
print(person)
add_numbers(5, 3) # 8
return vs print()
print() only DISPLAYS a value on screen. return actually HANDS BACK a value so it can be stored and
reused.
def add_print(a, b):
print(a + b) # just shows it
Note: Any time a function's output needs to be stored, reused, or passed elsewhere, it MUST use return, not just
print().
Note: Forgetting 'return' means the function gives back None by default, even if it collected data internally with
input().
Functions + conditionals
def check_grade(marks):
if marks >= 90:
return "Grade A"
elif marks >= 80:
return "Grade B"
else:
return "Grade C"
result = check_grade(85)
print(result) # Grade B
Note: return inside a loop STOPS the entire function immediately on the first match. Use print() inside the loop
instead, if you need every item processed, not just the first.
Functions + dictionaries
def print_student_info(student):
for key, value in [Link]():
print(f"{key}: {value}")
def show_sum(numbers):
total = 0
for num in numbers:
total += num
print(total)
my_list = get_numbers()
show_sum(my_list)
Note: Splitting work into two small functions (one collects data, one processes it) is how real programs stay
organized - each function has ONE clear job.
my_function() # prints 10
print(x) # ERROR - x doesn't exist outside the function
show_name() # Ali
Note: Variables created inside a function are destroyed once the function finishes. To use a value outside a function,
it must be returned and stored in an outer variable.
def check_grade():
marks = get_marks() # calling ANOTHER function from inside this one
if marks >= 90:
print("Grade A")
else:
print("Grade B")
check_grade()
main() structure
Once a program has several functions, it's common to create ONE main() function that calls the others in order,
acting as a clear 'table of contents' for what the program does.
def get_two_numbers():
a = int(input("Enter first number: "))
b = int(input("Enter second number: "))
return a, b
def main():
num1, num2 = get_two_numbers()
add_and_show(num1, num2)
main()
Note: You'll often see if __name__ == '__main__': main() at the bottom of real Python files - this means 'only run
main() if this file is run directly, not if it's imported elsewhere.' Deeper reasoning comes later when working with
multiple files/modules.
14. Coming Up Next
File handling (txt/csv/json), error handling (try/except), regular expressions, list/dict comprehensions, basic
OOP in Python (classes/objects - fast given existing C++ background), unit testing, then libraries (requests, os,
dotenv, AI SDKs for chatbots; pandas, numpy, matplotlib, streamlit for data analysis/dashboards), leading into
the first real mini-project.