1. Variables & Data Types
Show Answer
Mutable objects can be changed after creation (lists, dictionaries, sets), while immutable objects cannot be changed (strings, tuples, integers, floats).
# Mutable example
my_list = [1, 2, 3]
my_list[0] = 10 # This works
print(my_list) # [10, 2, 3]
# Immutable example
my_string = "Hello"
# my_string[0] = "h" # This would raise TypeError
Show Answer
Use type()
for exact type or isinstance()
for type checking including inheritance.
x = 10
print(type(x)) # <class 'int'>
print(isinstance(x, int)) # True
# isinstance is preferred for type checking
if isinstance(x, (int, float)):
print("x is a number")
Show Answer
==
checks for value equality, while is
checks for 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)
Show Answer
Python variables can hold different types of data during runtime without explicit type declaration.
x = 10 # x is an integer
print(type(x)) # <class 'int'>
x = "Hello" # x is now a string
print(type(x)) # <class 'str'>
x = [1, 2, 3] # x is now a list
print(type(x)) # <class 'list'>
Show Answer
Python raises a ZeroDivisionError
exception.
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"Error: {e}") # Error: division by zero
# For handling it gracefully
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
return "Cannot divide by zero"
Show Answer
Use built-in functions for type conversion: int()
, float()
, str()
, list()
, tuple()
, etc.
# String to integer
num = int("123") # 123
# Integer to string
text = str(123) # "123"
# String to list
chars = list("hello") # ['h', 'e', 'l', 'l', 'o']
# List to tuple
tup = tuple([1, 2, 3]) # (1, 2, 3)
2. Lists
Show Answer
Use a set to track seen elements or dict.fromkeys() for Python 3.7+:
# Method 1: Using set to track seen elements
def remove_duplicates(lst):
seen = set()
result = []
for item in lst:
if item not in seen:
seen.add(item)
result.append(item)
return result
# Method 2: Using dict.fromkeys() (Python 3.7+)
original = [1, 2, 3, 2, 4, 1, 5]
unique = list(dict.fromkeys(original))
print(unique) # [1, 2, 3, 4, 5]
Show Answer
append()
adds one element, extend()
adds multiple elements, insert()
adds at specific position.
lst = [1, 2, 3]
# append() - adds single element at end
lst.append(4)
print(lst) # [1, 2, 3, 4]
# extend() - adds multiple elements at end
lst.extend([5, 6])
print(lst) # [1, 2, 3, 4, 5, 6]
# insert() - adds element at specific index
lst.insert(0, 0)
print(lst) # [0, 1, 2, 3, 4, 5, 6]
Show Answer
Multiple approaches: sorting, using set, or single pass algorithm.
# Method 1: Using sorting
def second_largest_v1(lst):
unique_lst = list(set(lst))
if len(unique_lst) < 2:
return None
unique_lst.sort()
return unique_lst[-2]
# Method 2: Single pass
def second_largest_v2(lst):
if len(lst) < 2:
return None
first = second = float('-inf')
for num in lst:
if num > first:
second = first
first = num
elif num > second and num != first:
second = num
return second if second != float('-inf') else None
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(second_largest_v2(numbers)) # 6
Show Answer
In-place: reverse()
method. New list: reversed()
function or slicing.
original = [1, 2, 3, 4, 5]
# In-place reversal
lst1 = original.copy()
lst1.reverse() # Modifies the list
print(lst1) # [5, 4, 3, 2, 1]
# Creating new reversed list
lst2 = original[::-1] # Slicing
print(lst2) # [5, 4, 3, 2, 1]
lst3 = list(reversed(original)) # reversed() function
print(lst3) # [5, 4, 3, 2, 1]
print(original) # [1, 2, 3, 4, 5] - unchanged
Show Answer
Recursive approach to handle arbitrarily nested lists:
def flatten_list(lst):
result = []
for item in lst:
if isinstance(item, list):
result.extend(flatten_list(item))
else:
result.append(item)
return result
# Test
nested = [1, [2, 3], [4, [5, 6]], 7]
flat = flatten_list(nested)
print(flat) # [1, 2, 3, 4, 5, 6, 7]
# One-liner using recursion
flatten = lambda lst: [item for sublist in lst
for item in (flatten(sublist)
if isinstance(sublist, list) else [sublist])]
Show Answer
Use enumerate() to get index-value pairs and filter by value:
def find_all_indices(lst, target):
return [i for i, x in enumerate(lst) if x == target]
# Alternative using a loop
def find_all_indices_v2(lst, target):
indices = []
for i, value in enumerate(lst):
if value == target:
indices.append(i)
return indices
numbers = [1, 2, 3, 2, 4, 2, 5]
indices = find_all_indices(numbers, 2)
print(indices) # [1, 3, 5]
3. Tuples
Show Answer
Tuples are immutable, hashable, and have a fixed structure making them ideal for representing fixed data like coordinates.
# Good practice for coordinates
point = (10, 20) # x, y coordinates
rgb_color = (255, 128, 0) # Red, Green, Blue values
# Tuples can be used as dictionary keys
locations = {
(0, 0): "Origin",
(10, 20): "Point A",
(30, 40): "Point B"
}
# Tuples are hashable, lists are not
# locations = {[0, 0]: "Origin"} # This would raise TypeError
Show Answer
Python allows elegant variable swapping using tuple unpacking:
# Traditional way (other languages)
a, b = 10, 20
temp = a
a = b
b = temp
# Pythonic way using tuple unpacking
a, b = 10, 20
a, b = b, a # Swap values
print(a, b) # 20, 10
# Multiple variable swapping
x, y, z = 1, 2, 3
x, y, z = z, x, y
print(x, y, z) # 3, 1, 2
Show Answer
Tuple unpacking allows extracting values from tuples into separate variables:
# Basic unpacking
person = ("Alice", 25, "Engineer")
name, age, job = person
print(f"{name} is {age} years old and works as {job}")
# Function returning multiple values
def get_name_age():
return "Bob", 30
name, age = get_name_age()
# Using * for collecting remaining items
numbers = (1, 2, 3, 4, 5)
first, *middle, last = numbers
print(first) # 1
print(middle) # [2, 3, 4]
print(last) # 5
Show Answer
Add a comma after the element to create a single-element tuple:
# Wrong way - this creates an integer
not_tuple = (5)
print(type(not_tuple)) # <class 'int'>
# Correct way - comma makes it a tuple
single_tuple = (5,)
print(type(single_tuple)) # <class 'tuple'>
print(single_tuple) # (5,)
# Alternative without parentheses
another_tuple = 5,
print(type(another_tuple)) # <class 'tuple'>
Show Answer
Tuples themselves are immutable, but they can contain mutable objects that can be modified:
# Tuple is immutable
tup = (1, 2, 3)
# tup[0] = 10 # This would raise TypeError
# But tuple can contain mutable objects
tup_with_list = (1, [2, 3, 4], 5)
print(tup_with_list) # (1, [2, 3, 4], 5)
# You can modify the mutable object inside
tup_with_list[1].append(6)
print(tup_with_list) # (1, [2, 3, 4, 6], 5)
# But you cannot reassign the tuple element
# tup_with_list[1] = [7, 8, 9] # This would raise TypeError
Show Answer
Use list()
and tuple()
constructors for conversion:
# Tuple to list
my_tuple = (1, 2, 3, 4, 5)
my_list = list(my_tuple)
print(my_list) # [1, 2, 3, 4, 5]
print(type(my_list)) # <class 'list'>
# List to tuple
my_list = [1, 2, 3, 4, 5]
my_tuple = tuple(my_list)
print(my_tuple) # (1, 2, 3, 4, 5)
print(type(my_tuple)) # <class 'tuple'>
# Useful when you need to modify tuple data
original_tuple = (1, 2, 3)
temp_list = list(original_tuple)
temp_list.append(4)
new_tuple = tuple(temp_list)
print(new_tuple) # (1, 2, 3, 4)
5. Dictionaries
Show Answer
Use get()
method, in
operator, or try-except block:
student = {"name": "Alice", "age": 25}
# Method 1: Using get() with default value
grade = student.get("grade", "Not found")
print(grade) # "Not found"
# Method 2: Using 'in' operator
if "grade" in student:
print(student["grade"])
else:
print("Grade not found")
# Method 3: Try-except
try:
grade = student["grade"]
except KeyError:
grade = "Not found"
# Using get() for nested operations
score = student.get("test_scores", {}).get("math", 0)
Show Answer
Several methods depending on Python version and requirements:
dict1 = {"a": 1, "b": 2}
dict2 = {"b": 3, "c": 4}
# Method 1: Using ** operator (Python 3.5+)
merged = {**dict1, **dict2}
print(merged) # {'a': 1, 'b': 3, 'c': 4}
# Method 2: Using | operator (Python 3.9+)
merged = dict1 | dict2
print(merged) # {'a': 1, 'b': 3, 'c': 4}
# Method 3: Using update() (modifies original)
dict1_copy = dict1.copy()
dict1_copy.update(dict2)
print(dict1_copy) # {'a': 1, 'b': 3, 'c': 4}
# Method 4: Using dict() constructor
merged = dict(dict1, **dict2)
print(merged) # {'a': 1, 'b': 3, 'c': 4}
Show Answer
Use dictionary to track character counts:
def count_characters(text):
char_count = {}
for char in text:
char_count[char] = char_count.get(char, 0) + 1
return char_count
# Alternative using defaultdict
from collections import defaultdict
def count_characters_v2(text):
char_count = defaultdict(int)
for char in text:
char_count[char] += 1
return dict(char_count)
# Using Counter (most Pythonic)
from collections import Counter
def count_characters_v3(text):
return dict(Counter(text))
# Test
text = "hello world"
print(count_characters(text))
# {'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}
Show Answer
Use sorted()
with appropriate key function:
grades = {"Alice": 85, "Bob": 92, "Charlie": 78, "David": 95}
# Sort by keys (alphabetically)
sorted_by_keys = dict(sorted(grades.items()))
print(sorted_by_keys)
# {'Alice': 85, 'Bob': 92, 'Charlie': 78, 'David': 95}
# Sort by values (ascending)
sorted_by_values_asc = dict(sorted(grades.items(), key=lambda x: x[1]))
print(sorted_by_values_asc)
# {'Charlie': 78, 'Alice': 85, 'Bob': 92, 'David': 95}
# Sort by values (descending)
sorted_by_values_desc = dict(sorted(grades.items(), key=lambda x: x[1], reverse=True))
print(sorted_by_values_desc)
# {'David': 95, 'Bob': 92, 'Alice': 85, 'Charlie': 78}
Show Answer
These methods return different views of dictionary data:
student = {"name": "Alice", "age": 25, "grade": "A"}
# keys() - returns all keys
keys = student.keys()
print(keys) # dict_keys(['name', 'age', 'grade'])
print(list(keys)) # ['name', 'age', 'grade']
# values() - returns all values
values = student.values()
print(values) # dict_values(['Alice', 25, 'A'])
print(list(values)) # ['Alice', 25, 'A']
# items() - returns key-value pairs as tuples
items = student.items()
print(items) # dict_items([('name', 'Alice'), ('age', 25), ('grade', 'A')])
# Common usage in loops
for key in student.keys():
print(f"Key: {key}")
for value in student.values():
print(f"Value: {value}")
for key, value in student.items():
print(f"{key}: {value}")
Show Answer
Use zip()
function to pair elements from both lists:
keys = ["name", "age", "city", "job"]
values = ["Alice", 25, "New York", "Engineer"]
# Method 1: Using zip() and dict()
person = dict(zip(keys, values))
print(person) # {'name': 'Alice', 'age': 25, 'city': 'New York', 'job': 'Engineer'}
# Method 2: Dictionary comprehension
person = {k: v for k, v in zip(keys, values)}
print(person)
# Handle unequal length lists
keys_short = ["name", "age"]
values_long = ["Bob", 30, "Boston", "Doctor"]
# This will only use the shorter list's length
person = dict(zip(keys_short, values_long))
print(person) # {'name': 'Bob', 'age': 30}
6. Loops & Conditionals
Show Answer
break
exits loop, continue
skips iteration, pass
does nothing:
# break - exits the loop completely
for i in range(10):
if i == 5:
break # Loop stops here
print(i) # Prints: 0, 1, 2, 3, 4
# continue - skips current iteration
for i in range(10):
if i % 2 == 0:
continue # Skip even numbers
print(i) # Prints: 1, 3, 5, 7, 9
# pass - placeholder, does nothing
for i in range(5):
if i == 2:
pass # TODO: implement later
print(i) # Prints: 0, 1, 2, 3, 4
# pass is useful for empty functions/classes
def future_function():
pass # Will implement later
Show Answer
The else
clause executes when loop completes normally (not broken):
# for-else example
def find_item(items, target):
for item in items:
if item == target:
print(f"Found {target}")
break
else:
print(f"{target} not found") # Executes only if break never happened
# Test
find_item([1, 2, 3, 4, 5], 3) # Found 3
find_item([1, 2, 3, 4, 5], 6) # 6 not found
# while-else example
def find_factor(n):
i = 2
while i < n:
if n % i == 0:
print(f"{n} is not prime, factor: {i}")
break
i += 1
else:
print(f"{n} is prime")
find_factor(17) # 17 is prime
find_factor(15) # 15 is not prime, factor: 3
Show Answer
Generate Fibonacci sequence using loops:
def fibonacci_sequence(n):
if n <= 0:
return []
elif n == 1:
return [0]
elif n == 2:
return [0, 1]
fib_seq = [0, 1]
for i in range(2, n):
next_fib = fib_seq[i-1] + fib_seq[i-2]
fib_seq.append(next_fib)
return fib_seq
# Alternative using while loop
def fibonacci_while(n):
if n <= 0:
return []
fib_seq = []
a, b = 0, 1
count = 0
while count < n:
fib_seq.append(a)
a, b = b, a + b
count += 1
return fib_seq
# Test
print(fibonacci_sequence(10)) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Show Answer
Use zip()
to iterate over multiple sequences together:
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
cities = ["NY", "LA", "Chicago"]
# Basic zip usage
for name, age in zip(names, ages):
print(f"{name} is {age} years old")
# Multiple lists
for name, age, city in zip(names, ages, cities):
print(f"{name}, {age}, lives in {city}")
# With enumerate for index
for i, (name, age) in enumerate(zip(names, ages)):
print(f"{i}: {name} is {age}")
# Handle unequal length lists with itertools.zip_longest
from itertools import zip_longest
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c', 'd', 'e']
for num, char in zip_longest(list1, list2, fillvalue=0):
print(num, char) # (1, 'a'), (2, 'b'), (3, 'c'), (0, 'd'), (0, 'e')
Show Answer
Nested loops require special techniques to break out of multiple levels:
# Basic nested loop
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for i, row in enumerate(matrix):
for j, value in enumerate(row):
print(f"matrix[{i}][{j}] = {value}")
# Method 1: Using flag variable
def find_in_matrix(matrix, target):
found = False
for i, row in enumerate(matrix):
for j, value in enumerate(row):
if value == target:
print(f"Found {target} at position ({i}, {j})")
found = True
break
if found:
break
# Method 2: Using function with return
def find_in_matrix_v2(matrix, target):
for i, row in enumerate(matrix):
for j, value in enumerate(row):
if value == target:
return (i, j)
return None
# Method 3: Using exception handling
class BreakNestedLoop(Exception):
pass
def find_in_matrix_v3(matrix, target):
try:
for i, row in enumerate(matrix):
for j, value in enumerate(row):
if value == target:
raise BreakNestedLoop
except BreakNestedLoop:
return (i, j)
Show Answer
Multiple approaches to find prime numbers:
# Method 1: Basic approach
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
def primes_up_to(n):
primes = []
for num in range(2, n + 1):
if is_prime(num):
primes.append(num)
return primes
# Method 2: Sieve of Eratosthenes (more efficient)
def sieve_of_eratosthenes(n):
sieve = [True] * (n + 1)
sieve[0] = sieve[1] = False
for i in range(2, int(n**0.5) + 1):
if sieve[i]:
for j in range(i*i, n + 1, i):
sieve[j] = False
return [i for i in range(2, n + 1) if sieve[i]]
# Test
primes = primes_up_to(100)
print("Primes up to 100:", primes)
7. String Manipulation
Show Answer
Multiple approaches to reverse strings without slicing:
# Method 1: Using a loop
def reverse_string_loop(s):
result = ""
for char in s:
result = char + result
return result
# Method 2: Using recursion
def reverse_string_recursive(s):
if len(s) <= 1:
return s
return s[-1] + reverse_string_recursive(s[:-1])
# Method 3: Using list and join
def reverse_string_list(s):
char_list = list(s)
char_list.reverse()
return ''.join(char_list)
# Method 4: Using reversed()
def reverse_string_reversed(s):
return ''.join(reversed(s))
# Test
original = "Hello World"
print(reverse_string_loop(original)) # "dlroW olleH"
Show Answer
Different approaches to check palindromes:
# Method 1: Simple approach
def is_palindrome_simple(s):
return s == s[::-1]
# Method 2: Case-insensitive, ignoring spaces and punctuation
def is_palindrome_advanced(s):
# Remove non-alphanumeric and convert to lowercase
cleaned = ''.join(char.lower() for char in s if char.isalnum())
return cleaned == cleaned[::-1]
# Method 3: Two-pointer approach
def is_palindrome_two_pointers(s):
cleaned = ''.join(char.lower() for char in s if char.isalnum())
left, right = 0, len(cleaned) - 1
while left < right:
if cleaned[left] != cleaned[right]:
return False
left += 1
right -= 1
return True
# Test
print(is_palindrome_advanced("A man a plan a canal Panama")) # True
print(is_palindrome_advanced("race a car")) # False
Show Answer
Various methods to count words depending on requirements:
# Method 1: Using split() - simplest
def count_words_simple(text):
return len(text.split())
# Method 2: Handle multiple spaces and punctuation
def count_words_advanced(text):
import re
words = re.findall(r'\b\w+\b', text)
return len(words)
# Method 3: Manual counting
def count_words_manual(text):
count = 0
in_word = False
for char in text:
if char.isalpha():
if not in_word:
count += 1
in_word = True
else:
in_word = False
return count
# Test cases
test_text = "Hello, world! How are you today?"
print(count_words_simple(test_text)) # 5
print(count_words_advanced(test_text)) # 5
print(count_words_manual(test_text)) # 5
Show Answer
Find the longest common substring using dynamic programming:
def longest_common_substring(str1, str2):
m, n = len(str1), len(str2)
# Create a table to store lengths of common substrings
dp = [[0] * (n + 1) for _ in range(m + 1)]
max_length = 0
ending_pos_i = 0
# Fill the table
for i in range(1, m + 1):
for j in range(1, n + 1):
if str1[i-1] == str2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
if dp[i][j] > max_length:
max_length = dp[i][j]
ending_pos_i = i
else:
dp[i][j] = 0
# Extract the longest common substring
start_pos = ending_pos_i - max_length
return str1[start_pos:ending_pos_i]
# Simpler brute force approach
def longest_common_substring_brute(str1, str2):
longest = ""
for i in range(len(str1)):
for j in range(i + 1, len(str1) + 1):
substring = str1[i:j]
if substring in str2 and len(substring) > len(longest):
longest = substring
return longest
# Test
str1 = "programming"
str2 = "algorithm"
print(longest_common_substring(str1, str2)) # "gram"
Show Answer
Different methods to remove whitespace:
text = " Hello World \n\t Python "
# Method 1: Remove all whitespace characters
no_whitespace = ''.join(text.split())
print(repr(no_whitespace)) # 'HelloWorldPython'
# Method 2: Using replace() for specific whitespace
no_spaces = text.replace(' ', '').replace('\n', '').replace('\t', '')
print(repr(no_spaces)) # 'HelloWorldPython'
# Method 3: Using regular expressions
import re
no_whitespace_regex = re.sub(r'\s+', '', text)
print(repr(no_whitespace_regex)) # 'HelloWorldPython'
# Method 4: Remove only leading/trailing whitespace
stripped = text.strip()
print(repr(stripped)) # 'Hello World \n\t Python'
# Method 5: Replace multiple spaces with single space
single_spaces = re.sub(r'\s+', ' ', text.strip())
print(repr(single_spaces)) # 'Hello World Python'
Show Answer
Multiple ways to capitalize words:
# Method 1: Using built-in title()
def capitalize_words_builtin(text):
return text.title()
# Method 2: Using split() and join()
def capitalize_words_split(text):
words = text.split()
capitalized_words = [word.capitalize() for word in words]
return ' '.join(capitalized_words)
# Method 3: Manual approach preserving spacing
def capitalize_words_manual(text):
result = []
capitalize_next = True
for char in text:
if char.isalpha():
if capitalize_next:
result.append(char.upper())
capitalize_next = False
else:
result.append(char.lower())
else:
result.append(char)
capitalize_next = True
return ''.join(result)
# Method 4: Using regular expressions
import re
def capitalize_words_regex(text):
return re.sub(r'\b\w', lambda match: match.group(0).upper(), text.lower())
# Test
sentence = "hello world python programming"
print(capitalize_words_builtin(sentence)) # "Hello World Python Programming"
print(capitalize_words_manual("hello,world.python!programming")) # "Hello,World.Python!Programming"
8. Functions & Recursion
Show Answer
Parameters are variables in function definition, arguments are actual values passed when calling:
# Parameters are 'a' and 'b' in the function definition
def add_numbers(a, b): # a and b are parameters
return a + b
# Arguments are 5 and 3 when calling the function
result = add_numbers(5, 3) # 5 and 3 are arguments
# Types of parameters
def example_function(required_param,
default_param=10,
*args,
**kwargs):
print(f"Required: {required_param}")
print(f"Default: {default_param}")
print(f"Args: {args}")
print(f"Kwargs: {kwargs}")
# Calling with different argument types
example_function("hello", 20, 1, 2, 3, name="Alice", age=25)
Show Answer
Python follows LEGB rule: Local, Enclosing, Global, Built-in scope:
# Global scope
global_var = "I'm global"
def outer_function():
# Enclosing scope
enclosing_var = "I'm in enclosing scope"
def inner_function():
# Local scope
local_var = "I'm local"
# Accessing different scopes
print(local_var) # Local
print(enclosing_var) # Enclosing
1. How do you find the intersection of two lists using sets?
Show Answer
Convert lists to sets and use the intersection operation:
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
# Method 1: Using & operator
intersection = list(set(list1) & set(list2))
print(intersection) # [4, 5]
# Method 2: Using intersection() method
intersection = list(set(list1).intersection(set(list2)))
print(intersection) # [4, 5]
# Method 3: Preserving order from first list
intersection_ordered = [x for x in list1 if x in set(list2)]
print(intersection_ordered) # [4, 5]
2. What's the difference between union, intersection, and difference operations?
Show Answer
Set operations for combining or comparing sets:
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
# Union: all unique elements from both sets
union = set1 | set2 # or set1.union(set2)
print(f"Union: {union}") # {1, 2, 3, 4, 5, 6}
# Intersection: common elements
intersection = set1 & set2 # or set1.intersection(set2)
print(f"Intersection: {intersection}") # {3, 4}
# Difference: elements in set1 but not in set2
difference = set1 - set2 # or set1.difference(set2)
print(f"Difference: {difference}") # {1, 2}
# Symmetric difference: elements in either set but not both
sym_diff = set1 ^ set2 # or set1.symmetric_difference(set2)
print(f"Symmetric difference: {sym_diff}") # {1, 2, 5, 6}
3. How do you check if one set is a subset of another?
Show Answer
Use subset/superset methods or operators:
set_a = {1, 2, 3}
set_b = {1, 2, 3, 4, 5}
# Check if set_a is subset of set_b
is_subset = set_a <= set_b # or set_a.issubset(set_b)
print(f"Is {set_a} subset of {set_b}? {is_subset}") # True
# Check if set_b is superset of set_a
is_superset = set_b >= set_a # or set_b.issuperset(set_a)
print(f"Is {set_b} superset of {set_a}? {is_superset}") # True
# Proper subset (subset but not equal)
is_proper_subset = set_a < set_b
print(f"Is {set_a} proper subset of {set_b}? {is_proper_subset}") # True
4. Write a function to find unique elements that appear in exactly one of three lists.
Show Answer
Use set operations to find elements that appear in only one list:
def unique_in_one_list(list1, list2, list3):
set1, set2, set3 = set(list1), set(list2), set(list3)
# Elements unique to each set
unique_to_1 = set1 - set2 - set3
unique_to_2 = set2 - set1 - set3
unique_to_3 = set3 - set1 - set2
# Combine all unique elements
return list(unique_to_1 | unique_to_2 | unique_to_3)
# Test
list1 = [1, 2, 3, 4]
list2 = [3, 4, 5, 6]
list3 = [5, 6, 7, 8]
result = unique_in_one_list(list1, list2, list3)
print(result) # [1, 2, 7, 8] (order may vary)
5. How do you create an empty set vs an empty dictionary?
Show Answer
Use set()
for empty set, {}
creates empty dictionary:
# Empty set
empty_set = set()
print(type(empty_set)) # <class 'set'>
print(empty_set) # set()
# Empty dictionary (not empty set!)
empty_dict = {}
print(type(empty_dict)) # <class 'dict'>
print(empty_dict) # {}
# Adding elements
empty_set.add(1)
print(empty_set) # {1}
empty_dict['key'] = 'value'
print(empty_dict) # {'key': 'value'}
6. What happens when you try to add a mutable object to a set?
Show Answer
Sets can only contain hashable (immutable) objects. Adding mutable objects raises a TypeError:
# This works - immutable objects
my_set = {1, 2, 3, "hello", (1, 2, 3)}
print(my_set)
# This raises TypeError - mutable objects
try:
my_set.add([1, 2, 3]) # Lists are mutable
except TypeError as e:
print(f"Error: {e}") # unhashable type: 'list'
try:
my_set.add({1, 2, 3}) # Sets are mutable
except TypeError as e:
print(f"Error: {e}") # unhashable type: 'set'
# Convert to tuple if you need list-like data in set
my_set.add(tuple([1, 2, 3])) # This works
print(my_set)