Essential Python syntax and concepts
In Python, every value has a "truthiness" - it can be evaluated as either True or False in boolean contexts. Understanding which values are truthy vs falsy is crucial for writing clean, readable code.
empty_list = []
non_empty_list = [1, 5]
print(empty_list or 'hello') # hello
print(non_empty_list or 'hello') # [1, 5]The or operator uses short-circuit evaluation. It returns the first truthy value it encounters, or the last value if all are falsy.
Common Use Cases:
• Default values:
name = user_input or "Anonymous"config = get_config() or {}port = os.getenv("PORT") or 8080• Fallback values:
result = expensive_function() or cached_resultdata = fetch_from_api() or load_from_cache()image = user.profile_pic or "default.jpg"• Input validation:
if username and password: login(username, password)items = input_list or []Python has different division operators for different needs: regular division (/), floor division (//), and modulus (%) for remainders.
print(7 / 2) # Regular division: 3.5
print(7 // 2) # Floor division: 3
print(7 % 2) # Modulus (remainder): 1
print(-7 // 2) # Floor division: -4 (rounds down)
print(-7 % 2) # Modulus: 1Floor division (//) always rounds toward negative infinity, not toward zero.
Modulus (%) returns the remainder after division.
Common Use Cases:
• Cycling through arrays:
Use modulus to wrap around array indices, creating infinite loops through finite arrays.
colors = ["red", "green", "blue"]for i in range(10): current_color = colors[i % len(colors)] print(current_color) # red, green, blue, red, green...• Time conversion:
total_seconds = 3665hours = total_seconds // 3600minutes = (total_seconds % 3600) // 60seconds = total_seconds % 60print(f"{hours}:{minutes:02d}:{seconds:02d}") # 1:01:05# :02d means format as integer with 2 digits, zero-padded• Check even/odd numbers:
def is_even(n): return n % 2 == 0print(is_even(4)) # Trueprint(is_even(7)) # FalseDictionaries support various operations for sorting by keys/values and finding maximum values or keys. Here are the most common patterns.
# Sorting dictionary by keys and values (unsorted input)
numbers = {'zebra': 100, 'apple': 50, 'banana': 75}
sorted_keys = sorted(numbers.keys())
sorted_values = sorted(numbers.values())
print(sorted_keys) # ['apple', 'banana', 'zebra']
print(sorted_values) # [50, 75, 100]
# Lambda examples for complex sorting
students = {'alice': 85, 'bob': 92, 'charlie': 78}
# Sort by value (ascending)
by_grade_asc = sorted(students.items(), key=lambda x: x[1])
# Sort by value (descending)
by_grade_desc = sorted(students.items(), key=lambda x: x[1], reverse=True)
# Sort by name length
by_name_len = sorted(students.items(), key=lambda x: len(x[0]))
# sort() vs sorted() - KEY DIFFERENCE!
original_dict = {'c': 3, 'a': 1, 'b': 2}
keys_list = list(original_dict.keys())
sorted_copy = sorted(keys_list) # Returns new list
keys_list.sort() # Modifies original list
print(sorted_copy) # ['a', 'b', 'c']
print(keys_list) # ['a', 'b', 'c'] (modified!)
# Finding max value and key
scores = {'player1': 100, 'player2': 85, 'player3': 92}
max_score = max(scores.values())
best_player = max(scores, key=scores.get)
print(max_score) # 100
print(best_player) # player1
# WRONG: Mutating dictionary while iterating
data = {'a': 1, 'b': 2, 'c': 3}
# for key in data: # DON'T DO THIS
# if data[key] == 2:
# del data[key] # RuntimeError!
# CORRECT: Create a copy of keys first
for key in list(data.keys()):
if data[key] == 2:
del data[key] # Safe!
print(data) # {'a': 1, 'c': 3}sorted() returns a new sorted list, while sort() modifies the original list in-place.
Lambda functions provide custom sorting logic for complex data structures.
⚠️ Important: You cannot mutate a dictionary (e.g., using del) while iterating over it. Always create a copy of keys first with list(dict.keys()).
Common Use Cases:
• Leaderboards and rankings:
players = {'alice': 95, 'bob': 87, 'charlie': 92}top_player = max(players, key=players.get)leaderboard = sorted(players.items(), key=lambda x: x[1], reverse=True)• Inventory management by price:
inventory = {'laptop': 999, 'mouse': 25, 'keyboard': 75}cheapest_item = min(inventory, key=inventory.get)by_price = sorted(inventory.items(), key=lambda x: x[1])• Safe data filtering:
users = {'user1': 'active', 'user2': 'inactive', 'user3': 'active'}for user in list(users.keys()): if users[user] == 'inactive': del users[user]Lists support powerful slicing operations and can be manipulated using lambda functions with built-in functions like filter() and map().
# List slicing with ::-1 (reverse)
my_list = [1, 2, 3, 4, 5]
reversed_list = my_list[::-1]
print(reversed_list) # [5, 4, 3, 2, 1]
# String reversal using ::-1
text = "hello"
reversed_text = text[::-1]
print(reversed_text) # olleh
# Lambda with filter() - find multiples of 3
my_list = range(16)
multiples_of_3 = filter(lambda x: x % 3 == 0, my_list)
print(list(multiples_of_3)) # [0, 3, 6, 9, 12, 15]
# Lambda with map() - square all numbers
numbers = [1, 2, 3, 4, 5]
squared = map(lambda x: x ** 2, numbers)
print(list(squared)) # [1, 4, 9, 16, 25]
# Lambda with sorted() - sort by custom criteria
students = [('Alice', 85), ('Bob', 90), ('Charlie', 78)]
sorted_by_grade = sorted(students, key=lambda student: student[1])
print(sorted_by_grade) # [('Charlie', 78), ('Alice', 85), ('Bob', 90)]Slice notation [start:stop:step] where ::-1 means "everything, but backwards".Lambda functions create anonymous functions for short, simple operations.
Common Use Cases:
Regular expressions are powerful patterns for matching and extracting text. The re module provides regex functionality in Python.
import re
# Basic pattern matching examples
s = "CodesignalIsAwesome"
splitOne = re.findall('.[^A-Z]*', s)
print(splitOne) # ['Codesignal', 'Is', 'Awesome']
# Count quoted strings pattern: \"[^\"]*\"
def countQuotedStrings(inputString):
matches = re.findall(r'(\"[^\"]*\")', inputString)
return len(matches)
print(countQuotedStrings('[[0, 20], [33, 99]]')) # 0
print(countQuotedStrings('[ \"one\", 2, \"three\" ]')) # 2
print(countQuotedStrings('[\"oh, no! kind, of, tricky\", \"test, case\"]')) # 2
# Extract quoted strings only
def findStrings(text):
return re.findall(r'\"[^\"]*\"', text)
print(findStrings('[\"apple\", 42, \"banana\"]')) # ['\"apple\"', '\"banana\"']
# Extract numbers only
def findNumbers(text):
return re.findall(r'\d+', text)
print(findNumbers('[\"apple\", 42, \"banana\", 99]')) # ['42', '99']
print(findNumbers('I have 5 apples and 12 oranges')) # ['5', '12']
print(findNumbers('Room 101, Floor 25, Building 7')) # ['101', '25', '7']
# Extract boolean values only
def findBooleans(text):
return re.findall(r'\b(true|false)\b', text)
print(findBooleans('[true, \"test\", false, 42]')) # ['true', 'false']
# Extract only digits: \d+
def extractDigits(inputString):
return re.findall(r'(\d+)', inputString)
print(extractDigits('[[0, 20], [33, 99]]')) # ['0', '20', '33', '99']
print(extractDigits('Call me at 555-1234 or 987-6543')) # ['555', '1234', '987', '6543']
print(extractDigits('Price: $29.99, Weight: 4 lbs')) # ['29', '99', '4']
# Extract individual alphanumeric chars: [a-zA-Z0-9]
def extractChars(inputString):
return re.findall(r'[a-zA-Z0-9]', inputString)
print(extractChars('111')) # ['1', '1', '1']
print(extractChars('true')) # ['t', 'r', 'u', 'e']. - Matches any character (except newline)* - Zero or more instances of preceding character+ - One or more instances of preceding character^ - Beginning of line OR "not" inside brackets\d - Any digit (equivalent to [0-9])[A-Z] - Any uppercase letter[^A-Z] - Any character that is NOT uppercase\"[^\"]*\" - Match quoted strings (anything between quotes)\d+ - Match one or more consecutive digits[a-zA-Z0-9] - Match any single alphanumeric character(\"[^\"]*\"|\d+|true|false) - Match strings OR numbers OR booleans([^aeiou])(.*) - Any non-vowel + any characters^([aeiou])(.*) - Vowel at start + any characters^([^aeiou])(.*) - Non-vowel at start + any charactersParentheses create capture groups to store matched substrings for later reference.^([aeiouy])(.) captures a vowel and any character separately.
\n - Newline, \t - Tab, \r - Carriage return\' - Literal single quote, \" - Literal double quote\\ - Literal backslash characterAdvanced list operations including reversing, sorting, comparisons, and string manipulation techniques that are essential for coding interviews.
# reversed() function - works with any sequence
numbers = [1, 2, 3, 4, 5]
reversed_list = list(reversed(numbers))
print(reversed_list) # [5, 4, 3, 2, 1]
# Sort list of lists by specific index/key
sample_list = [['10', 100], ['2', 200], ['5', 150]]
# Sort by first element (as integer to avoid lexicographic issues)
sample_list.sort(key=lambda x: int(x[0]))
print(sample_list) # [['2', 200], ['5', 150], ['10', 100]]
# Sort by second column
list1 = [[2, 100], [6, 20], [10, 19], [4, 54]]
list1.sort(key=lambda x: x[1])
print(list1) # [[10, 19], [6, 20], [4, 54], [2, 100]]
# Sort by length
list2 = [[100, 200, 300, 400, 500], [100, 200, 300], [100, 150, 200, 400]]
list2.sort(key=len)
print(len(list2[0])) # 3 (shortest list first)
# sort() vs sorted() - key difference!
original = [3, 1, 4, 2]
sorted_copy = sorted(original) # Returns new list
print(original) # [3, 1, 4, 2] - unchanged
print(sorted_copy) # [1, 2, 3, 4]
# Check if all elements are equal
listOfStrings = ['hello', 'hello', 'hello']
all_equal1 = listOfStrings[1:] == listOfStrings[:-1] # Slice comparison
all_equal2 = all(elem == listOfStrings[0] for elem in listOfStrings)
print(all_equal1, all_equal2) # True True
# Increment all elements by 1
input_list = [1, 2, 3, 4]
new_list = [x + 1 for x in input_list]
print(new_list) # [2, 3, 4, 5]
# String character swapping function
def swap(c, i, j):
c = list(c) # Convert to list
c[i], c[j] = c[j], c[i] # Swap
return ''.join(c) # Convert back
s = 'hello'
print(swap(s, 1, 4)) # hollesort(key=lambda x: int(x[0])) - Avoid lexicographic issues with string numberssort(key=lambda x: x[1]) - Sort by specific column/indexsort(key=len) - Sort by lengthsorted() returns new list, sort() modifies originallst[1:] == lst[:-1] - Quick equality checkall(elem == lst[0] for elem in lst) - All elements equal[x+1 for x in lst] - Transform all elementslist(reversed(sequence)) - Reverse any sequenceint() for numeric sortingUnderstanding hidden advantages of data structures and when to use lesser-known but powerful options for coding interviews.
# Tuples: Immutable, faster iteration, heterogeneous data
person = ("Alice", 25, "Engineer", 75000.50)
coordinates = (40.7128, -74.0060)
# Tuple unpacking and multiple assignment
name, age, job, salary = person
x, y = coordinates
a, b = b, a # Variable swapping!
# Collections for advanced use cases
from collections import Counter, defaultdict, deque
# Counter - frequency counting made easy
text = "hello world"
char_count = Counter(text)
print(char_count.most_common(2)) # [('l', 3), ('o', 2)]
# defaultdict - no KeyError worries
groups = defaultdict(list)
groups['team1'].append('Alice') # No KeyError!
groups['team1'].append('Bob')
print(dict(groups)) # {'team1': ['Alice', 'Bob']}
# deque - efficient queue operations
queue = deque([1, 2, 3])
queue.appendleft(0) # Add to front - O(1)
queue.append(4) # Add to back - O(1)
first = queue.popleft() # Remove from front - O(1)
print(list(queue)) # [1, 2, 3, 4]
# Sets - O(1) lookups and unique elements
seen = set()
duplicates = [1, 2, 2, 3, 3, 4]
unique = list(set(duplicates)) # Remove duplicates
print(unique) # [1, 2, 3, 4] (order not guaranteed)
# frozenset - immutable set for dict keys
# WHY frozenset? Regular sets can't be dict keys!
regular_set = {'read', 'write'}
# cache = {regular_set: "result"} # TypeError: unhashable type
# SOLUTION: Use frozenset
permissions = frozenset(['read', 'write', 'execute'])
admin_perms = frozenset(['read', 'write', 'execute', 'admin'])
# Example 1: Role mapping (frozenset as keys)
role_mapping = {
permissions: 'user',
admin_perms: 'admin',
frozenset(['read']): 'guest'
}
print(role_mapping[permissions]) # user
# Example 2: Caching expensive operations
cache = {}
def get_access_level(user_permissions):
perm_key = frozenset(user_permissions)
if perm_key in cache:
return cache[perm_key] # Fast lookup!
# Simulate expensive database query or API call
result = f"access_level_for_{len(perm_key)}_permissions"
cache[perm_key] = result
return result
print(get_access_level(['read', 'write']))
# Example 3: Set operations still work
basic_perms = frozenset(['read', 'write'])
advanced_perms = frozenset(['read', 'write', 'execute', 'admin'])
print(advanced_perms - basic_perms) # frozenset({'execute', 'admin'})
print(basic_perms | advanced_perms) # Union
print(basic_perms & advanced_perms) # Intersection
print('read' in basic_perms) # True - O(1) lookup
# Example 4: Why not just use tuples?
tuple_perms = ('read', 'write', 'read') # Allows duplicates!
frozen_perms = frozenset(['read', 'write', 'read'])
print(len(tuple_perms)) # 3 (keeps duplicates)
print(len(frozen_perms)) # 2 (removes duplicates)
print('admin' in tuple_perms) # False - O(n) search
print('admin' in frozen_perms) # False - O(1) searchEssential Python tricks and built-in functions that frequently appear in coding interviews but are easy to forget.
# Multi-line code with backslash
print("Hello \
world") # Hello world
# ASCII conversion functions
print(ord('z')) # 122 - character to ASCII
print(chr(99 + 4)) # g - ASCII to character
print(ord('A')) # 65
print(ord('a') - ord('A')) # 32 - case difference
# Rounding functions
import math
x = round(2.3) # 2 - rounds to nearest
y = round(3.9) # 4
z = math.ceil(4.1) # 5 - always rounds up
b = math.floor(7.8) # 7 - always rounds down
print(math.ceil(1)) # 1 - works with integers too
# Useful built-in functions for interviews
nums = [1, 2, 3, 4, 5]
print(sum(nums)) # 15 - sum of all elements
print(min(nums)) # 1
print(max(nums)) # 5
print(len(nums)) # 5
# String methods that save time
text = " hello world "
print(text.strip()) # "hello world" - remove whitespace
print(text.split()) # ['hello', 'world']
print(" ".join(['a', 'b'])) # "a b"
print("abc".isalpha()) # True - all letters
print("123".isdigit()) # True - all digits
# Enumerate and zip for cleaner loops
letters = ['a', 'b', 'c']
for i, letter in enumerate(letters):
print(f"{i}: {letter}") # 0: a, 1: b, 2: c
numbers = [1, 2, 3]
for letter, num in zip(letters, numbers):
print(f"{letter}-{num}") # a-1, b-2, c-3ord(char) - Convert character to ASCII valuechr(num) - Convert ASCII value to characterord('a') - ord('A') - Case difference is always 32round(x) - Round to nearest integermath.ceil(x) - Always round upmath.floor(x) - Always round down.isalpha(), .isdigit(), .isalnum()a, b = b, a for swapping