Python Basics: Syntax, Variables, Data Types, and String Operations
A comprehensive introduction to Python syntax covering indentation rules, variables, all core data types, type operations, string methods, and all operator categories with real working examples.
Python Basics: Syntax, Variables, Data Types, and String Operations
Python is one of the most readable programming languages ever designed. Its creator, Guido van Rossum, intentionally made the syntax close to plain English. That readability comes with strict rules ā especially around indentation ā that beginners must understand from day one.
This guide covers everything from how Python thinks about whitespace, to variables, to every core data type, to the full string manipulation toolkit. By the end, you will write Python that is not just correct, but idiomatic.
1. Indentation: Python's Most Important Rule
Most languages use curly braces {} to group code blocks. Python uses indentation ā the whitespace at the start of a line. This is not stylistic preference; it is syntax.
# This is correct Python
if True:
print("This line is inside the if block")
print("So is this line")
print("This line is outside the if block")# This raises an IndentationError
if True:
print("Missing indentation") # IndentationError!The Golden Rule: Consistency
Python does not care whether you use 2 spaces, 4 spaces, or a tab ā but you must be consistent within a block. The Python community has standardized on 4 spaces per level (PEP 8).
# WRONG: mixing tabs and spaces (Python 3 raises TabError)
if True:
print("4 spaces")
print("tab") # TabError!
# RIGHT: 4 spaces consistently
if True:
print("level 1")
if True:
print("level 2")
if True:
print("level 3")Why Indentation as Syntax?
This design forces readable code. In languages with braces, developers debate brace placement styles. In Python, there is only one way. The visual structure of your code is the structure of your program.
# You can see the nesting at a glance
def process_users(users):
for user in users:
if user["active"]:
if user["age"] >= 18:
print(f"Adult active user: {user['name']}")
else:
print(f"Minor active user: {user['name']}")
else:
print(f"Inactive user: {user['name']}")2. print() and input()
print()
print() outputs text to the console. It is the first function almost every Python developer learns.
# Basic usage
print("Hello, World!")
# Multiple arguments ā separated by space by default
print("Name:", "Alice", "Age:", 30)
# Output: Name: Alice Age: 30
# Custom separator
print("2026", "04", "17", sep="-")
# Output: 2026-04-17
# Custom end character (default is newline \n)
print("Loading", end="")
print("...", end="")
print(" Done!")
# Output: Loading... Done!
# Print nothing (empty line)
print()
# Print a list or other object
numbers = [1, 2, 3]
print(numbers)
# Output: [1, 2, 3]Printing with Formatting
name = "Alice"
score = 98.5
rank = 1
# Old-style % formatting (still seen in legacy code)
print("Student: %s, Score: %.1f" % (name, score))
# str.format() method
print("Student: {}, Score: {:.1f}".format(name, score))
# f-strings (modern, preferred since Python 3.6)
print(f"Student: {name}, Score: {score:.1f}, Rank: #{rank}")
# Output: Student: Alice, Score: 98.5, Rank: #1input()
input() reads a line of text from the user. It always returns a string.
# Basic input
name = input("What is your name? ")
print(f"Hello, {name}!")
# Input always returns string ā convert when needed
age_str = input("How old are you? ")
age = int(age_str) # Convert to integer
print(f"In 10 years you will be {age + 10}")
# Common mistake: forgetting to convert
age = input("Age: ")
# print(age + 10) # TypeError: can only concatenate str (not "int") to str
# Safe input with validation
while True:
try:
age = int(input("Enter your age: "))
break
except ValueError:
print("Please enter a valid number.")3. Variables
Variables are labels that point to values stored in memory. Python is dynamically typed ā you do not declare types, the interpreter infers them.
Variable Assignment
# Simple assignment
x = 10
name = "Alice"
is_active = True
# Multiple assignment on one line
a, b, c = 1, 2, 3
print(a, b, c) # 1 2 3
# Swap variables (Python's elegant idiom)
a, b = b, a
print(a, b) # 2 1
# Assign the same value to multiple variables
x = y = z = 0
print(x, y, z) # 0 0 0
# Augmented assignment
count = 0
count += 1 # count = count + 1
count += 1
print(count) # 2
score = 100
score -= 15 # subtract
score *= 2 # multiply
score //= 3 # integer divide
print(score) # 56Naming Rules
# Valid variable names
user_name = "Alice" # snake_case (PEP 8 recommended)
userName = "Bob" # camelCase (not recommended in Python)
_private = "secret" # leading underscore = convention for private
__dunder__ = "special" # double underscore = dunder/magic (avoid in user code)
MAX_SIZE = 100 # ALL_CAPS = convention for constants
counter1 = 0 # letters and digits (not at start)
# Invalid names
# 1counter = 0 # SyntaxError: cannot start with digit
# my-var = 0 # SyntaxError: hyphens not allowed
# class = "A" # SyntaxError: reserved keyword
# Check reserved keywords
import keyword
print(keyword.kwlist)
# ['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await',
# 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',
# 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',
# 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try',
# 'while', 'with', 'yield']Variables Are References
Understanding that variables are references (not boxes) is crucial:
# Integers are immutable ā reassignment creates a new object
x = 5
y = x # y points to the same 5
x = 10 # x now points to 10; y still points to 5
print(x, y) # 10 5
# Lists are mutable ā both variables point to the same list
list_a = [1, 2, 3]
list_b = list_a # list_b is NOT a copy; it's the same list
list_a.append(4)
print(list_b) # [1, 2, 3, 4] ā list_b sees the change!
# To copy: use .copy() or list()
list_c = list_a.copy()
list_a.append(5)
print(list_c) # [1, 2, 3, 4] ā list_c is independent4. Core Data Types
Python has several built-in data types. Understanding which type to use ā and why ā is a core skill.
4.1 int (Integer)
Whole numbers, positive or negative, with no size limit in Python 3.
age = 25
year = 2026
big_number = 1_000_000 # underscores for readability (Python 3.6+)
negative = -42
zero = 0
# Integer literals in different bases
binary = 0b1010 # binary: 10
octal = 0o17 # octal: 15
hexadecimal = 0xFF # hexadecimal: 255
print(binary, octal, hexadecimal) # 10 15 255
# Integer operations
print(7 // 2) # 3 ā integer (floor) division
print(7 % 2) # 1 ā modulo (remainder)
print(2 ** 10) # 1024 ā exponentiation
# Python 3 integers have unlimited precision
factorial_20 = 1
for i in range(1, 21):
factorial_20 *= i
print(factorial_20) # 2432902008176640000 (exact, no overflow)4.2 float (Floating Point)
Numbers with decimal points, following IEEE 754 double precision.
pi = 3.14159
temperature = -12.5
scientific = 1.5e3 # 1500.0
small = 2.5e-4 # 0.00025
print(type(pi)) # <class 'float'>
# Float arithmetic precision issue (famous gotcha)
print(0.1 + 0.2) # 0.30000000000000004 (NOT 0.3!)
print(0.1 + 0.2 == 0.3) # False!
# Solution: use round() for comparison or decimal module
print(round(0.1 + 0.2, 2) == 0.3) # True
# For financial calculations, use decimal.Decimal
from decimal import Decimal
print(Decimal("0.1") + Decimal("0.2")) # 0.3 (exact)
# Special float values
import math
print(math.inf) # inf
print(-math.inf) # -inf
print(math.nan) # nan (Not a Number)
print(math.isnan(math.nan)) # True4.3 str (String)
Strings are immutable sequences of Unicode characters.
# String creation ā single, double, or triple quotes
name = 'Alice'
greeting = "Hello"
multiline = """This is
a multiline
string."""
# String with quotes inside
quote1 = "She said 'hello'"
quote2 = 'He replied "hi there"'
escaped = "It's a \"beautiful\" day"
# Raw strings ā backslash is literal (useful for regex, Windows paths)
path = r"C:\Users\Alice\Documents"
pattern = r"\d+\.\d+"
print(len(name)) # 5
print(name[0]) # A
print(name[-1]) # e
print(name[1:4]) # lic (slicing)
print(name[::-1]) # ecilA (reverse)4.4 bool (Boolean)
Only two values: True and False. In Python, bool is a subclass of int.
is_active = True
is_deleted = False
print(type(is_active)) # <class 'bool'>
print(True + True) # 2 (bool is subclass of int!)
print(True * 5) # 5
print(False + 1) # 1
# Boolean from comparisons
x = 10
print(x > 5) # True
print(x == 5) # False
print(x != 5) # True
# Truthy and Falsy values
# Falsy: False, 0, 0.0, "", [], {}, set(), None
# Truthy: everything else
print(bool(0)) # False
print(bool("")) # False
print(bool([])) # False
print(bool(None)) # False
print(bool(1)) # True
print(bool("hi")) # True
print(bool([0])) # True (list with one item, even if item is falsy)4.5 None
None represents the absence of a value. It is Python's null.
result = None
print(result) # None
print(type(result)) # <class 'NoneType'>
# None is a singleton ā always use 'is' to compare, not '=='
if result is None:
print("No result yet")
# Functions that don't return explicitly return None
def greet(name):
print(f"Hello, {name}")
output = greet("Alice") # prints: Hello, Alice
print(output) # None
# None as a default parameter sentinel
def connect(host, port=None):
if port is None:
port = 443
print(f"Connecting to {host}:{port}")
connect("api.example.com") # Connecting to api.example.com:443
connect("api.example.com", 8080) # Connecting to api.example.com:80805. type() and isinstance()
type()
Returns the exact type of an object.
print(type(42)) # <class 'int'>
print(type(3.14)) # <class 'float'>
print(type("hello")) # <class 'str'>
print(type(True)) # <class 'bool'>
print(type(None)) # <class 'NoneType'>
print(type([1, 2, 3])) # <class 'list'>
print(type({"a": 1})) # <class 'dict'>
# Using type() in conditions (usually avoid this pattern)
x = 42
if type(x) == int:
print("x is an int")isinstance()
Checks if an object is an instance of a class or any of its subclasses. Prefer this over type() for type checking.
x = 42
print(isinstance(x, int)) # True
print(isinstance(x, float)) # False
print(isinstance(x, (int, float))) # True ā check multiple types
# Why isinstance is better: it respects inheritance
class Animal:
pass
class Dog(Animal):
pass
rex = Dog()
print(type(rex) == Animal) # False ā type() is exact
print(isinstance(rex, Animal)) # True ā isinstance checks hierarchy
print(isinstance(rex, Dog)) # True
# Practical use: validate function inputs
def calculate_area(radius):
if not isinstance(radius, (int, float)):
raise TypeError(f"radius must be a number, got {type(radius).__name__}")
if radius <= 0:
raise ValueError("radius must be positive")
return 3.14159 * radius ** 2
print(calculate_area(5)) # 78.53975
# calculate_area("big") # TypeError: radius must be a number, got str6. Type Casting
Converting between types explicitly.
int()
# String to int
age = int("25")
print(age, type(age)) # 25 <class 'int'>
# Float to int ā truncates (does NOT round)
x = int(3.9)
print(x) # 3 (not 4!)
y = int(-3.9)
print(y) # -3 (truncates toward zero)
# Bool to int
print(int(True)) # 1
print(int(False)) # 0
# Invalid conversions raise ValueError
# int("hello") # ValueError: invalid literal for int()
# int("3.14") # ValueError: float string needs float() first
# From other bases
print(int("0b1010", 2)) # 10 (binary string)
print(int("FF", 16)) # 255 (hex string)
print(int("17", 8)) # 15 (octal string)float()
# String to float
price = float("19.99")
print(price, type(price)) # 19.99 <class 'float'>
# Int to float
x = float(5)
print(x) # 5.0
# Bool to float
print(float(True)) # 1.0
print(float(False)) # 0.0
# Special strings
print(float("inf")) # inf
print(float("-inf")) # -inf
print(float("nan")) # nanstr()
# Any type to string
print(str(42)) # "42"
print(str(3.14)) # "3.14"
print(str(True)) # "True"
print(str(None)) # "None"
print(str([1, 2, 3])) # "[1, 2, 3]"
# Useful for string concatenation with non-strings
age = 30
# print("Age: " + age) # TypeError!
print("Age: " + str(age)) # "Age: 30"
# Better: use f-string
print(f"Age: {age}") # "Age: 30"bool()
# Explicit conversion
print(bool(0)) # False
print(bool(1)) # True
print(bool(-1)) # True (any non-zero)
print(bool("")) # False
print(bool(" ")) # True (whitespace is truthy!)
print(bool([])) # False
print(bool([0])) # TrueReal-world Type Conversion Example
# Parsing user data from a form or CSV
raw_data = {
"name": "Alice",
"age": "28",
"salary": "75000.50",
"is_manager": "true",
"department_id": "42"
}
parsed = {
"name": raw_data["name"],
"age": int(raw_data["age"]),
"salary": float(raw_data["salary"]),
"is_manager": raw_data["is_manager"].lower() == "true",
"department_id": int(raw_data["department_id"])
}
print(parsed)
# {'name': 'Alice', 'age': 28, 'salary': 75000.5, 'is_manager': True, 'department_id': 42}7. String Methods
Strings are objects in Python, and they come with a rich set of built-in methods. All string methods return a new string ā strings are immutable.
Case Methods
text = "Hello, World!"
print(text.upper()) # HELLO, WORLD!
print(text.lower()) # hello, world!
print(text.title()) # Hello, World!
print(text.capitalize()) # Hello, world! (only first char)
print(text.swapcase()) # hELLO, wORLD!
# Practical use: case-insensitive comparison
user_input = "YeS"
if user_input.lower() == "yes":
print("User confirmed")Whitespace Methods
messy = " hello world "
print(repr(messy.strip())) # 'hello world' (both sides)
print(repr(messy.lstrip())) # 'hello world ' (left only)
print(repr(messy.rstrip())) # ' hello world' (right only)
# Strip specific characters
url = "///path/to/resource///"
print(url.strip("/")) # path/to/resource
csv_line = "Alice,28,Engineer\n"
print(csv_line.strip()) # Alice,28,EngineerSearch and Test Methods
sentence = "The quick brown fox jumps over the lazy dog"
# Finding
print(sentence.find("fox")) # 16 (index of first occurrence)
print(sentence.find("cat")) # -1 (not found)
print(sentence.index("fox")) # 16 (same but raises ValueError if not found)
print(sentence.count("the")) # 1 (case sensitive)
print(sentence.count("the", 0, len(sentence))) # 1
# Testing
print(sentence.startswith("The")) # True
print(sentence.endswith("dog")) # True
print(sentence.startswith(("The", "A"))) # True (tuple of options)
# Character testing
print("hello123".isalnum()) # True (letters and digits)
print("hello".isalpha()) # True (letters only)
print("12345".isdigit()) # True (digits only)
print(" ".isspace()) # True (whitespace only)
print("HELLO".isupper()) # True
print("hello".islower()) # True
print("Hello World".istitle()) # Truesplit() and join()
# split() ā string to list
sentence = "the quick brown fox"
words = sentence.split() # split on whitespace
print(words) # ['the', 'quick', 'brown', 'fox']
csv_line = "Alice,28,New York,Engineer"
fields = csv_line.split(",")
print(fields) # ['Alice', '28', 'New York', 'Engineer']
# Split with max splits
print("a:b:c:d".split(":", 2)) # ['a', 'b', 'c:d']
# splitlines() for multi-line text
poem = "Roses are red\nViolets are blue\nPython is great"
print(poem.splitlines())
# ['Roses are red', 'Violets are blue', 'Python is great']
# join() ā list to string
words = ["the", "quick", "brown", "fox"]
print(" ".join(words)) # the quick brown fox
print("-".join(words)) # the-quick-brown-fox
print("".join(words)) # thequickbrownfox
# Common pattern: build CSV line
fields = ["Alice", "28", "Engineer"]
csv_line = ",".join(fields)
print(csv_line) # Alice,28,Engineer
# Performance tip: always use join() to concatenate many strings
# SLOW: building a string with +=
result = ""
for i in range(1000):
result += str(i) # creates a new string each iteration!
# FAST: collect parts, then join
parts = []
for i in range(1000):
parts.append(str(i))
result = "".join(parts)replace()
text = "I love cats. Cats are great. Cats rule!"
# Replace all occurrences
print(text.replace("Cats", "Dogs"))
# I love cats. Dogs are great. Dogs rule!
# Note: case-sensitive
print(text.replace("cats", "dogs"))
# I love dogs. Cats are great. Cats rule!
# Replace with count limit
print(text.replace("Cats", "Dogs", 1))
# I love cats. Dogs are great. Cats rule!
# Chaining replacements
dirty = " Hello, World! "
clean = dirty.strip().replace(",", "").replace(" ", " ")
print(clean) # Hello World!format() and f-strings
# str.format() ā positional
print("Hello, {}! You are {} years old.".format("Alice", 28))
# str.format() ā named
print("Name: {name}, Age: {age}".format(name="Alice", age=28))
# str.format() ā formatting numbers
print("{:.2f}".format(3.14159)) # 3.14
print("{:,}".format(1000000)) # 1,000,000
print("{:>10}".format("hi")) # " hi" (right-align, width 10)
print("{:<10}".format("hi")) # "hi " (left-align)
print("{:^10}".format("hi")) # " hi " (center)
print("{:0>5}".format("42")) # "00042" (zero-pad)
# f-strings (Python 3.6+) ā preferred modern approach
name = "Alice"
age = 28
score = 98.756
print(f"Name: {name}, Age: {age}")
print(f"Score: {score:.2f}") # Score: 98.76
print(f"Double age: {age * 2}") # Double age: 56
print(f"Uppercase: {name.upper()}") # Uppercase: ALICE
# f-string debugging (Python 3.8+)
x = 42
print(f"{x=}") # x=42
print(f"{x * 2=}") # x * 2=84
# Multiline f-strings
user = {"name": "Alice", "city": "Oslo"}
message = (
f"Dear {user['name']},\n"
f"Welcome from {user['city']}!\n"
f"Best regards"
)
print(message)Other Useful String Methods
# zfill() ā zero-pad
print("42".zfill(5)) # 00042
print("042".zfill(5)) # 00042
# center(), ljust(), rjust()
print("hi".center(10)) # " hi "
print("hi".center(10, "*")) # "****hi****"
# encode() ā to bytes
text = "Hello"
encoded = text.encode("utf-8")
print(encoded) # b'Hello'
print(encoded.decode()) # Hello
# in operator ā membership test
print("fox" in "the quick brown fox") # True
print("cat" in "the quick brown fox") # False8. Arithmetic Operators
a = 17
b = 5
print(a + b) # 22 ā addition
print(a - b) # 12 ā subtraction
print(a * b) # 85 ā multiplication
print(a / b) # 3.4 ā true division (always returns float)
print(a // b) # 3 ā floor division (rounds down to integer)
print(a % b) # 2 ā modulo (remainder)
print(a ** b) # 1419857 ā exponentiation
# Integer division and modulo relationship
# a == (a // b) * b + (a % b)
print(17 == (17 // 5) * 5 + 17 % 5) # True
# Modulo with negative numbers (Python follows mathematical convention)
print(-7 % 3) # 2 (not -1!) ā result has same sign as divisor
print(7 % -3) # -2 ā result has same sign as divisor
# Floor division
print(-7 // 2) # -4 (rounds toward negative infinity)
print(7 // 2) # 3
# Operator precedence (PEMDAS / BODMAS)
print(2 + 3 * 4) # 14 (not 20)
print((2 + 3) * 4) # 20
print(2 ** 3 ** 2) # 512 (right-to-left: 3**2=9, 2**9=512)
print((2 ** 3) ** 2) # 64 (left-to-right)
# Augmented assignment operators
x = 10
x += 5 # x = x + 5 ā 15
x -= 3 # x = x - 3 ā 12
x *= 2 # x = x * 2 ā 24
x //= 5 # x = x // 5 ā 4
x **= 3 # x = x ** 3 ā 64
x %= 10 # x = x % 10 ā 4
print(x) # 4Math Module
import math
print(math.sqrt(16)) # 4.0
print(math.ceil(3.2)) # 4 (round up)
print(math.floor(3.8)) # 3 (round down)
print(math.abs(-5)) # AttributeError! ā use abs() built-in
print(abs(-5)) # 5
print(math.pow(2, 8)) # 256.0 (returns float)
print(2 ** 8) # 256 (returns int)
print(math.log(100, 10)) # 2.0
print(math.log2(8)) # 3.0
print(math.pi) # 3.141592653589793
print(math.e) # 2.718281828459045
# Trigonometry (angles in radians)
print(math.sin(math.pi / 2)) # 1.0
print(math.cos(0)) # 1.0
print(math.degrees(math.pi)) # 180.0
print(math.radians(180)) # 3.1415926535897939. Comparison Operators
Comparison operators return True or False.
a = 10
b = 20
print(a == b) # False ā equal to
print(a != b) # True ā not equal to
print(a < b) # True ā less than
print(a > b) # False ā greater than
print(a <= b) # True ā less than or equal to
print(a >= b) # False ā greater than or equal to
# Chained comparisons (unique to Python)
x = 15
print(10 < x < 20) # True ā elegant!
print(0 <= x <= 100) # True
# Equivalent to: 10 < x and x < 20
# But more readable and only evaluates x once
# Identity operators: is vs ==
# == checks VALUE equality
# is checks IDENTITY (same object in memory)
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True ā same values
print(a is b) # False ā different objects
print(a is c) # True ā same object
# None comparison: always use 'is'
result = None
print(result == None) # True (works but not recommended)
print(result is None) # True (correct way)
print(result is not None) # False
# Surprising: Python caches small integers (-5 to 256)
x = 256
y = 256
print(x is y) # True (cached)
x = 257
y = 257
print(x is y) # False (not cached ā different objects)
# This is an implementation detail; don't rely on it10. Logical Operators
and, or, and not combine boolean expressions.
# and ā True if both operands are True
print(True and True) # True
print(True and False) # False
print(False and True) # False
print(False and False) # False
# or ā True if at least one operand is True
print(True or True) # True
print(True or False) # True
print(False or True) # True
print(False or False) # False
# not ā inverts boolean
print(not True) # False
print(not False) # True
# Practical examples
age = 22
has_id = True
is_vip = False
# Check entry
if age >= 18 and has_id:
print("Entry allowed")
# Check discount
if age < 25 or is_vip:
print("Discount applies")
# Check NOT banned
is_banned = False
if not is_banned:
print("User can log in")Short-Circuit Evaluation
Python stops evaluating as soon as it can determine the result ā this is called short-circuiting.
# and: if first is False, skip second
def expensive_check():
print("Running expensive check...")
return True
result = False and expensive_check() # expensive_check never called!
print(result) # False
result = True and expensive_check() # expensive_check IS called
print(result) # True
# or: if first is True, skip second
result = True or expensive_check() # expensive_check never called!
print(result) # Trueand/or Return Values (Not Just True/False)
This is a Python subtlety many beginners miss:
# and returns first falsy value, or last value if all truthy
print(1 and 2) # 2
print(0 and 2) # 0
print("a" and "b") # "b"
print("" and "b") # ""
# or returns first truthy value, or last value if all falsy
print(1 or 2) # 1
print(0 or 2) # 2
print("" or "default") # "default"
print(None or []) # []
# Practical idiom: default values
name = ""
display_name = name or "Anonymous"
print(display_name) # Anonymous
config = None
settings = config or {}
print(settings) # {}11. A Complete Working Example
Let's combine everything into a small BMI calculator:
def calculate_bmi():
"""BMI calculator demonstrating all covered concepts."""
print("=" * 40)
print(" BMI CALCULATOR")
print("=" * 40)
# Input with type conversion
while True:
try:
weight_str = input("Enter your weight (kg): ").strip()
weight = float(weight_str)
if weight <= 0:
print("Weight must be positive.")
continue
break
except ValueError:
print(f"'{weight_str}' is not a valid number. Try again.")
while True:
try:
height_str = input("Enter your height (m): ").strip()
height = float(height_str)
if height <= 0:
print("Height must be positive.")
continue
break
except ValueError:
print(f"'{height_str}' is not a valid number. Try again.")
# Arithmetic
bmi = weight / (height ** 2)
# Comparison and logical operators
if bmi < 18.5:
category = "Underweight"
advice = "Consider consulting a nutritionist."
elif 18.5 <= bmi < 25.0:
category = "Normal weight"
advice = "Great! Keep it up."
elif 25.0 <= bmi < 30.0:
category = "Overweight"
advice = "Consider more physical activity."
else:
category = "Obese"
advice = "Please consult a healthcare professional."
# String formatting
print("\n" + "=" * 40)
print(f" Weight: {weight:.1f} kg")
print(f" Height: {height:.2f} m")
print(f" BMI: {bmi:.1f}")
print(f" Status: {category}")
print(f" Advice: {advice}")
print("=" * 40)
# Boolean result
is_healthy = 18.5 <= bmi < 25.0
print(f"\nHealthy range: {is_healthy}")
return bmi
# Uncomment to run interactively:
# calculate_bmi()
# For demonstration, test with known values
weight, height = 70.0, 1.75
bmi = weight / height ** 2
print(f"BMI for {weight}kg at {height}m: {bmi:.2f}")
# BMI for 70.0kg at 1.75m: 22.86Key Takeaways
- Indentation is syntax ā use 4 spaces consistently. Never mix tabs and spaces.
- Variables are references ā mutable objects (lists, dicts) can be modified through any reference pointing to them.
- None is not zero or empty ā always compare with
is None, not== None. - Floats are approximate ā never use
==to compare floats; useround()ormath.isclose(). - isinstance() beats type() ā it respects inheritance and is the Pythonic way to check types.
- Strings are immutable ā all string methods return new strings. Assign the result.
- Use f-strings (Python 3.6+) ā they are the most readable and fastest string formatting option.
- Short-circuit evaluation ā use
x or defaultas a concise way to provide fallback values. - Type casting is explicit ā Python will not implicitly convert
"5"to5. You must callint(). - and/or return values, not just booleans ā learn this; it unlocks many Pythonic idioms.
Common Mistakes to Avoid
# Mistake 1: Comparing None with ==
result = None
if result == None: # Works but wrong style
pass
if result is None: # Correct
pass
# Mistake 2: Modifying a string "in place"
name = "alice"
name.upper() # Does nothing useful ā returns new string
print(name) # still "alice"
name = name.upper() # Correct: assign the result
print(name) # "ALICE"
# Mistake 3: Float equality
if 0.1 + 0.2 == 0.3: # This is False!
print("equal")
import math
if math.isclose(0.1 + 0.2, 0.3): # Correct
print("approximately equal")
# Mistake 4: Forgetting input() returns a string
age = input("Age: ")
# if age > 18: # TypeError: '>' not supported between str and int
if int(age) > 18: # Correct
# Mistake 5: Using 'is' for value comparison
a = 1000
b = 1000
if a is b: # May be False (outside cached range)
print("same")
if a == b: # Correct for value comparison
print("equal") # TrueEnjoyed this article?
Explore the Backend Systems learning path for more.
Found this helpful?
Leave a comment
Have a question, correction, or just found this helpful? Leave a note below.