📊 Day 01 : Data Types and Memory
🎯 Enterprise Objective
Mastering Python isn't just about knowing syntax; it's about understanding how data is fundamentally stored, accessed, and optimized in memory. Today, we deconstruct Python's 10 foundational data types. You will learn not only how to use them, but when to use them to write high-performance, production-grade analytical pipelines.
📋 Strategic Data Type Matrix
| # | Type | Immutable? | Memory Cost | Enterprise Analytics Use Case |
|---|---|---|---|---|
| 1 | int | ✅ Yes | Variable | Primary keys, absolute indexing, discrete counts. |
| 2 | float | ✅ Yes | 24 bytes | Continuous measurements, financial metrics, probabilities. |
| 3 | complex | ✅ Yes | 32 bytes | Signal processing, geospatial vectors, quantum modeling. |
| 4 | str | ✅ Yes | Variable | Raw text mining, log parsing, categorical identifiers. |
| 5 | bool | ✅ Yes | 28 bytes | Binary masks, conditional filtering, boolean logic. |
| 6 | list | ❌ No | Dynamic | Ordered queues, chronological time-series buffers. |
| 7 | tuple | ✅ Yes | Fixed | Immutable configuration matrices, compound dictionary keys. |
| 8 | set | ❌ No | Dynamic | O(1) deduplication, cohort intersection/union analysis. |
| 9 | dict | ❌ No | Dynamic | Fast O(1) lookups, JSON payload structuring, aggregations. |
| 10 | None | ✅ Yes | 16 bytes | Singleton representation of missing/null values. |
1. Integer (int) :
An integer is a whole number that can be positive, negative, or zero, and it does not contain a decimal point. Unlike many other programming languages such as C or Java, Python integers support arbitrary precision, meaning they can grow to very large values limited only by your system's memory.
Examples: 10, -25, 0, 999999
x = 10**100 # A 101-digit number!
print(x)
💼 Why Data Analysts Care
Integers are the foundational blocks of tracking entities and loops.
• Row Counts: Functions like len(df) return integers.
• Primary Keys: Customer ID, Order ID, and Transaction ID are typically stored as integers for high-speed indexing.
• Categorical Encoding: Converting string categories to integers (0 = Low, 1 = Medium, 2 = High) is a standard requirement for Machine Learning.
⚠️ Common Pitfall: Division Behavior
In Python, the standard division operator / always returns a float, even if the result is mathematically whole.
print(10 / 2) # Output: 5.0 (float)
print(10 // 2) # Output: 5 (int) - Use floor division to keep it an integer!
-7 // 2 yields -4).🧠 Memory Insight
A standard Python integer uses about 28 bytes. For large-scale data processing (millions of rows), this is highly inefficient. Professional analysts use NumPy and pandas optimized types to compress data footprint.
| Optimized Type | Memory Usage | Range |
|---|---|---|
int8 | 1 byte | -128 to 127 |
int16 | 2 bytes | -32K to 32K |
int32 | 4 bytes | ~±2 billion |
🧪 Concept Checks: int
Q1. Create a = 15 and b = 4. Compute and print: a + b, a b, a // b, a % b, a * b. Verify each result's type with type().
Q2. Write code that checks whether 2 ** 100 overflows. Print the result. How does Python handle arbitrarily large integers?
Q3. Given x = 42, convert it to: float (float(x)), string (str(x)), and boolean (bool(x)). Print each result and its type.
Q4. Write code to extract the tens digit from n = 4567 using integer arithmetic only (// and %). Expected: 6.
Q5. Compute 10 // 3 and 10 / 3. Print both results and their types. Explain why // is called floor division.
2. Float (float) : Decimal Numbers & Continuous Metrics
A float represents continuous numerical data containing a decimal point or expressed in scientific e-notation. Python internally uses the 64-bit IEEE 754 double-precision standard, providing approximately 15-17 significant decimal digits of precision.
Examples: 3.14, -0.001, 2.5e2
pi = 3.1415926535
scientific = 2.5e3 # 2500.0
💼 Why Data Analysts Care
Floats are the absolute backbone of continuous modeling.
• Financial Engineering: Tracking revenue, prices, and transaction amounts.
• Statistical Modeling: Almost all analytical measures (Mean, Standard Deviation, Z-Scores) naturally evaluate to floats.
• Geospatial Analytics: Latitude and longitude coordinates require deep decimal precision.
⚠️ Common Pitfall: The Floating-Point Trap
Because computers operate in base-2 (binary) fractions, they cannot perfectly represent all base-10 decimals. 0.1 + 0.2 will evaluate to 0.30000000000000004.
import math
print(math.isclose(0.1 + 0.2, 0.3)) # Output: True
decimal.Decimal module.🧠 Special Float Values
Floats support unique architectural values critical for handling messy, real-world data:
float('nan'): The universal standard for missing data in Pandas.float('inf'): Used to represent mathematical bounds.
🧪 Concept Checks: float
Q1. Print 0.1 + 0.2. Is the result exactly 0.3? Write code using round() and math.isclose() to properly compare floats.
Q2. Write code to convert temperature_f = 98.6 to Celsius using (f - 32) * 5/9. Print the result rounded to 2 decimal places.
Q3. Create price = 19.99 and quantity = 3. Compute total = price * quantity. Why is the result not exactly 59.97? Fix it with round().
Q4. Demonstrate float overflow: compute 1e308 * 2. What does Python return? Then try 1e-324 / 10. What happens with underflow?
Q5. Use float('inf'), float('-inf'), and float('nan'). Test: inf > 1000000 → True, nan == nan → False. Print all results.
3. Complex (complex) : Multi-Dimensional Vectors
A complex number consists of a real part and an imaginary part. Python natively supports them out of the box, using the j suffix (instead of i like in mathematics) to denote the imaginary unit.
Examples: 3+4j, -1j, 5.2+2j
z = 3 + 4j
print(z.real) # Output: 3.0
print(z.imag) # Output: 4.0
💼 Why Data Analysts Care
While rare in standard business intelligence, complex numbers are indispensable in specialized scientific fields.
• Signal Processing: Using Fast Fourier Transforms (FFT) to analyze audio or sensor frequencies.
• Electrical Engineering: Modeling alternating currents, phases, and impedance.
• Vector Math: Instantly compute the magnitude (length) of the vector using the built-in abs() function.
⚠️ Common Pitfall: Comparison Operators
Complex numbers reside on a 2D plane. Therefore, they cannot be ordered sequentially using > or < like integers or floats.
# (3 + 4j) > (1 + 2j) <-- Raises TypeError!
print((3 + 4j) == (3 + 4j)) # You can only check for equality
int() or float(). You must explicitly extract the .real part.🧠 Memory Insight
Because a complex number stores two double-precision floats under the hood, it consumes more memory (32 bytes). In large-scale computing, NumPy handles arrays of complex numbers using highly optimized complex64 or complex128 types.
🧪 Concept Checks: complex
Q1. Create z = 3 + 4j. Print its .real, .imag, and compute the magnitude using abs(z). Verify: sqrt(3² + 4²) = 5.
Q2. Add (2 + 3j) and (4 - 1j). Print the result. Then multiply them and print. Show complex arithmetic works naturally.
Q3. Write code to check if type(5j) is complex. Then check if isinstance(5j, (int, float, complex)) returns True.
Q4. Convert the integer 7 to a complex number using complex(7). What is its imaginary part? Print complex(3, 4) and verify.
Q5. Try complex('3+4j') (string parsing). Then try complex('3 + 4j') with spaces — does it work? Show the error handling.
4. String (str) : Unstructured Text Data
A string is an ordered, immutable sequence of Unicode characters. It is used to represent any textual data and can be defined using single, double, or triple quotes for multi-line text.
Examples: "Alice", 'New York', '''Multi-line text'''
greeting = "Hello, World!"
print(greeting[0]) # Output: 'H'
💼 Why Data Analysts Care
A vast majority of raw data exists as unstructured text. Analysts spend up to 80% of their time cleaning it.
• Categorical Features: Representing non-numerical dimensions (e.g., Region, Product_Tier).
• Log Parsing: Extracting precise metadata (timestamps, IPs, error codes) from raw server logs.
• Dynamic Reporting: Using f-strings to seamlessly inject variables directly into dashboard strings.
⚠️ Common Pitfall: Immutability
Strings are immutable. Once created, they cannot be modified in-place. Every operation (like .replace() or .upper()) creates a brand new string object in RAM.
s = "cat"
# s[0] = "b" <-- Raises TypeError!
s = "b" + s[1:] # Correct way: reassign to a new string
data.strip().lower().replace('x', 'y') is clean but computationally expensive on millions of rows because it generates multiple temporary strings.🧠 Memory Insight: String Interning
Python optimizes memory by "interning" short, identifier-like strings. If multiple variables are assigned "revenue", Python stores the word "revenue" only once in RAM. This makes dictionary key lookups blazing fast via O(1) pointer comparison.
🧪 Concept Checks: str
Q1. Create a multi-line string using triple quotes. Print it. Then create the same using \n. Verify both produce identical output.
Q2. Given name = 'alice', chain .strip().title() and print. Then use an f-string: f'{name.title()} has {len(name)} letters'.
Q3. Write code to check if 'Python' contains 'tho' using the in operator. Then use .find() and .index(). Show what happens with .index() when not found.
Q4. Demonstrate string immutability: try s = 'hello'; s[0] = 'H'. Catch the error. Show the correct way: s = 'H' + s[1:].
Q5. Given data = ' Alice, 30, NYC ', split by comma, strip each part, and print as a clean list: ['Alice', '30', 'NYC'].
5. Boolean (bool) : Binary Logic & Masks
A boolean represents exactly one of two binary states: True or False. Under the hood, Python's bool is a strict subclass of the integer type (True evaluates to 1, and False evaluates to 0).
Examples: True, False
is_active = True
print(type(is_active)) # Output: <class 'bool'>
💼 Why Data Analysts Care
Booleans are the fundamental building blocks of dataset filtering and conditional flow.
• Boolean Masking: Filtering Pandas datasets using boolean arrays (e.g., df[df['salary'] > 100000]).
• State Flags: Tracking binary conditions (has_purchased, is_churned).
• Instant Aggregations: Because True = 1, you can instantly count matches by summing a boolean array (sum([True, False, True]) yields 2).
⚠️ Common Pitfall: Truthy vs Falsy
Python evaluates objects in conditional statements based on their "Truthiness". Empty structures are strictly evaluated as Falsy (e.g., 0, 0.0, '', [], {}, None).
my_list = []
if not my_list:
print("This evaluates because the list is Falsy!")
" " or the literal text "False" is Truthy because the string is technically not empty!🧠 The Logical Short-Circuit
Python's logical operators (and, or) use short-circuit evaluation for maximum performance. In A and B, if A is False, Python stops instantly without ever evaluating B. Always place your most computationally expensive checks on the right side!
🧪 Concept Checks: bool
Q1. Test truthiness of: bool(0), bool(''), bool([]), bool(None), bool(0.0). Print each. Then test: bool(1), bool('hello'), bool([1]). What pattern do you see?
Q2. Write code: x = 10; print(x > 5 and x < 20). Then use chained comparison: print(5 < x < 20). Verify both give the same result.
Q3. Demonstrate True == 1 and False == 0. Then show: True + True + True → 3. Explain why booleans are integers in Python.
Q4. Write a one-liner using bool() to check if a list items = [1, 2, 3] is non-empty. Then check an empty list. Explain why if items: works.
Q5. Use any() and all() on [True, False, True]. Print both. Then test on [0, '', None] and [1, 'a', [1]]. Explain the results.
6. NoneType (None) : The Null State
The NoneType is a special data type that has exactly one valid value: None. It is Python's native way to represent the absolute absence of a value, null, or "nothing". It is not equal to 0, False, or an empty string.
Examples: None
missing_value = None
print(type(missing_value)) # Output: <class 'NoneType'>
💼 Why Data Analysts Care
None is critical for handling incomplete, corrupt, or uninitialized data states.
• Missing Data: Before data reaches a Pandas DataFrame (where it becomes NaN), raw Python handles missing records securely as None.
• Safe Default Arguments: Used natively to initialize optional parameters in custom analytical functions without triggering memory leaks.
• API Nulls: When reading from a SQL database or a JSON API, NULL values are automatically translated into Python None objects.
⚠️ Common Pitfall: The Mutable Default Argument Trap
A catastrophic error in Python is using a mutable type (like a list or dict) as a default argument in a function. The list will persist across all function calls!
# CORRECT WAY: Use None to initialize!
def add_item(item, basket=None):
if basket is None:
basket = []
basket.append(item)
return basket
🧠 Memory Insight: The Singleton Pattern
None is a strict memory singleton. There is only ever one instance of None existing in your computer's RAM at any given time. Because of this, you must always check for None using the identity operator is (e.g., if val is None:) instead of the equality operator ==. This validates the strict memory address and prevents accidental truthy/falsy evaluation errors.
🧪 Concept Checks: None
Q1. Write a function find_item(lst, target) that returns the index if found, None if not. Call it and check the result with is None (not == None).
Q2. Show that None is a singleton: a = None; b = None; print(a is b) → True. Explain why is is preferred over == for None checks.
Q3. Create a list [1, None, 3, None, 5]. Write code to filter out None values using a list comprehension with is not None. Print the clean list.
Q4. Demonstrate None as a default parameter: def greet(name=None): return f'Hello, {name or "World"}'. Test with and without argument.
Q5. Check the boolean value of None: bool(None) → False. Write an if statement that handles None, 0, and '' differently from each other.
7. List (list) : Dynamic & Mutable Sequences
A list is an ordered, mutable collection of arbitrary objects created using square brackets []. Python lists are dynamic arrays of memory pointers—they can grow or shrink on demand and hold mixed data types simultaneously.
Examples: [1, 2, 3], ['Alice', 30, True]
users = ["Alice", "Bob"]
users.append("Charlie") # Grows dynamically in-place
print(users)
💼 Why Data Analysts Care
Lists are the most versatile structure for holding sequenced data.
• Time-Series Buffers: Sequentially appending streaming data chronologically.
• Schema Definitions: Passing ordered column names into DataFrame operations.
• Batch Aggregations: Accumulating results dynamically during loops or list comprehensions ([x**2 for x in data]).
⚠️ Common Pitfall: The Shallow Copy Trap
Because lists are mutable, assigning a list to a new variable creates a memory reference, not an independent copy. Altering the new list will permanently corrupt the original list!
list_a = [1, 2, 3]
list_b = list_a # Points to the exact same memory address!
list_b.append(4) # Corrupts list_a as well
.copy() or slicing [:]. Furthermore, never remove items from a list while actively looping over it via a for loop.🧠 Performance Insight (Big-O Bottleneck)
Lists are highly inefficient for large-scale searching and numerical math. Checking x in my_list executes in O(N) time (Python scans elements one-by-one). For heavy math, switch to NumPy arrays. For fast lookups, convert to a Set.
🧪 Concept Checks: list
Q1. Create nums = [5, 2, 8, 1, 9]. Use .sort(), .reverse(), .append(6), .pop(), .insert(0, 10). Print after each operation.
Q2. Demonstrate list mutability: a = [1, 2, 3]; b = a; b.append(4). Print both a and b. Why did a change? Fix it with b = a.copy().
Q3. Write code to access: first element, last element, slice [1:3], every 2nd element [::2], and reversed [::-1] from [10,20,30,40,50].
Q4. Create a nested list matrix = [[1,2],[3,4],[5,6]]. Access element 4 using double indexing. Flatten it to [1,2,3,4,5,6] using a loop.
Q5. Given words = ['hello','world'], show that words * 3 repeats the list and words + ['python'] concatenates. Print both results.
8. Tuple (tuple) : Immutable Records
A tuple is an ordered, immutable sequence of elements created using parentheses (). Because tuples cannot be changed after creation, Python allocates exact, fixed memory blocks for them, making them highly secure and slightly faster than lists.
Examples: (10, 20), ('red', 'green', 'blue')
coordinates = (40.7128, -74.0060)
print(coordinates[0]) # Output: 40.7128
💼 Why Data Analysts Care
Tuples store fixed, heterogeneous records where the position of the data has strict meaning.
• Data Integrity: Safeguarding static reference data (like RGB constants, database connection URLs) from accidental mutation.
• Compound Dictionary Keys: Because tuples are immutable (hashable), they can be used to construct multi-dimensional dictionary keys (which lists cannot do).
• Function Returns: Seamlessly packing and unpacking multiple return values (clicks, impressions = get_metrics()).
⚠️ Common Pitfall: Single-Element Tuples
A common mistake when creating a tuple with exactly one element is forgetting the trailing comma.
t1 = (5) # This is just an integer in parentheses!
t2 = (5,) # This is a valid single-element tuple
🧠 Memory Insight
Tuples instantiate faster and consume slightly less memory than lists because they lack dynamic resizing overhead. A list pre-allocates extra memory blocks to allow for fast .append() operations, whereas a tuple allocates exactly the memory it needs.
🧪 Concept Checks: tuple
Q1. Create point = (3, 4). Unpack into x, y. Compute distance from origin: (x2 + y2) ** 0.5. Print the result.
Q2. Try point[0] = 10. Catch the TypeError. Then show that a tuple containing a list t = (1, [2,3]) allows t[1].append(4). Explain why.
Q3. Use tuple unpacking with : first, middle, last = (1, 2, 3, 4, 5). Print each variable. What type is middle?
Q4. Create a single-element tuple: t = (42,). Show that t = (42) without the comma is just an integer. Print type() of both.
Q5. Use a tuple as a dictionary key: locations = {(40.7, -74.0): 'NYC'}. Try the same with a list as key. Show the TypeError.
9. Set (set) : O(1) Unique Collections
A set is an unordered, mutable collection of strictly unique elements. Sets are backed by highly optimized Hash Tables in C, sacrificing element ordering to provide lightning-fast mathematical operations and lookups.
Examples: {1, 2, 3}, {'apple', 'banana'}
unique_ids = {101, 102, 103, 101}
print(unique_ids) # Duplicates automatically dropped! Output: {101, 102, 103}
💼 Why Data Analysts Care
Sets are the ultimate tool for rapid cohort comparisons and pipeline deduplication.
• Instant Deduplication: Instantly stripping duplicate values from massive, messy arrays (list(set(raw_data))).
• Cohort Analysis: Rapidly computing intersections (users active in both Q1 and Q2) and unions.
• Security & Filtering: Validating IDs against a blacklist in constant time.
⚠️ Common Pitfall: Unhashable Elements
Sets can only store immutable (hashable) objects. You cannot place a list or a dictionary inside a set.
# invalid_set = { [1, 2], [3, 4] } <-- Raises TypeError!
valid_set = { (1, 2), (3, 4) } # Tuples are hashable!
{} (that creates an empty dictionary). You must explicitly call set().🧠 Performance Insight: O(1) Lookups
Checking membership (x in my_set) executes in O(1) constant time. Python passes the value into a mathematical hash function, instantly calculating its exact location in RAM. It takes the exact same amount of time to find an ID in a set of 10 items as it does in a set of 10 million items!
🧪 Concept Checks: set
Q1. Create a = {1,2,3,4} and b = {3,4,5,6}. Compute and print: union (|), intersection (&), difference (-), symmetric difference (^).
Q2. Given names = ['Alice','Bob','Alice','Charlie','Bob'], convert to a set to get unique names. Convert back to sorted list. Print the result.
Q3. Demonstrate set's O(1) lookup: check 'Alice' in large_set vs 'Alice' in large_list for a 100K-element collection. Time both.
Q4. Create a frozenset from {1,2,3}. Try .add(4). Show the error. Use frozenset as a dict key — prove it works unlike regular sets.
Q5. Write code to find common elements between 3 sets using chained &. Test: {1,2,3} & {2,3,4} & {3,4,5} → {3}.
10. Dictionary (dict) : High-Speed Key-Value Stores
A dictionary is a mutable, ordered collection of key-value pairs. Like sets, dictionaries are powered by highly optimized Hash Tables. Keys must be strictly unique and immutable, while values can be absolutely any object.
Examples: {'name': 'Alice', 'age': 30}
employee = {
"id": 1042,
"role": "Data Analyst",
"skills": ["Python", "SQL"]
}
print(employee["role"]) # Output: 'Data Analyst'
💼 Why Data Analysts Care
Dictionaries are the architectural backbone of structured data transfer and aggregation in Python.
• JSON & API Ingestion: Dictionaries map perfectly to JSON format, making them the default structure for ingesting web API payloads.
• In-Memory Lookups: Simulating rapid-access relational lookups without the overhead of spinning up a full SQL database.
• Frequency Counters: Rapidly tallying categorical occurrences (e.g., word frequencies, error codes).
⚠️ Common Pitfall: The KeyError Crash
Accessing a missing key via strict bracket notation will immediately crash your script, bringing down entire data pipelines.
emp = {"name": "Alice"}
# print(emp["salary"]) <-- Raises KeyError!
print(emp.get("salary", 0)) # Professional standard: Safely returns 0
for item in my_dict:), Python only yields the keys. To iterate over both, use for k, v in my_dict.items():.🧠 The Dictionary Hash Table
Dictionaries provide O(1) lookups for keys. When you query emp["skills"], Python hashes the string "skills" to calculate the exact memory bucket where the value is stored, making mapping operations blazingly fast.
🧪 Concept Checks: dict
Q1. Create emp = {'name':'Alice', 'dept':'Eng', 'salary':85000}. Access using [] and .get(). Show [] raises KeyError for missing keys but .get() returns None.
Q2. Iterate over a dict three ways: .keys(), .values(), .items(). Print each. Use .items() in a formatted f-string loop.
Q3. Merge two dicts: d1 = {'a':1, 'b':2} and d2 = {'b':3, 'c':4} using {d1, d2}. Print result. Which value wins for key 'b'?
Q4. Use .setdefault() to build a frequency counter: loop through 'banana', using d.setdefault(char, 0) then incrementing. Print the dict.
Q5. Create a dict comprehension: {x: x**2 for x in range(1, 6)}. Then filter: keep only entries where value > 10. Print both.
🛠️ Professional Practice Tasks
Theory is useless without muscle memory. Complete these tasks to solidify your understanding.
Task 1 (Type Inspector): Write a function inspect(value) that prints: the value, type(), isinstance() checks against int/float/str/bool/list/dict, truthiness (bool()), and sys.getsizeof(). Test with 6 different types.
Task 2 (Type Converter): Write a function smart_convert(value) that takes a string and returns: int if it's a whole number, float if decimal, bool if 'true'/'false', None if 'none'/empty, else the original string. Test with 8 inputs.
Task 3 (Data Record): Build a complete record using ALL types: {'id':1, 'name':'Alice', 'salary':85000.50, 'is_active':True, 'skills':['Python','SQL'], 'scores':(90,85,92), 'tags':{'senior','lead'}, 'manager':None}. Access and print each field with its type.
Task 4 (Mutable vs Immutable Lab): Write experiments proving: strings, tuples, ints are immutable (show id changes on 'modification'). Lists, dicts, sets are mutable (show id stays same). Print id() before and after each operation.
Task 5 (Type Gotchas): Demonstrate 5 common type pitfalls: (1) 0.1+0.2!=0.3, (2) mutable default args, (3) is vs == for ints >256, (4) list * with nested refs, (5) dict key with unhashable type. Print each gotcha with explanation.
💻 Pure Coding Interview Questions
Q1.
Write a function type_of(value) that returns a human-readable type name: type_of(42) → 'integer', type_of([1]) → 'list'. Handle all built-in types.
Q2.
Write code that proves Python integers have unlimited precision: compute 2**1000 and print the number of digits. Compare with other languages.
Q3.
Write a function safe_cast(value, target_type, default=None) that safely converts between types, returning default on failure.
Q4.
Write a function deep_type_check(obj) that recursively reports types in nested structures: {'a': [1, 'hello', (True, None)]} → full type tree.
Q5.
Write code demonstrating that True + True = 2 and False * 10 = 0. Use this to count True values in a list using sum().
Q6.
Write a function flatten_types(lst) that takes a mixed list [1, 'a', [2, [3]], (4,)] and returns a flat list of all atomic values with their types.
Q7.
Write a function is_numeric(value) that returns True for int, float, complex, and numeric strings like '42', '3.14', '2+3j'. Handle edge cases.
Q8.
Write code showing the difference between == and is for: small ints (cached), large ints, strings (interned), lists, and None.
Q9.
Write a function coerce_types(a, b) that returns both values cast to the 'wider' type: int+float→float, float+complex→complex, any+str→str.
Q10.
Write a function dict_to_namedtuple(name, d) that converts a dict to a namedtuple. Test with {'x':1, 'y':2} → Point(x=1, y=2).
Q11.
Write a function memory_report(*values) that prints each value, its type, and sys.getsizeof(). Compare: int, float, str, list, tuple, dict, set.
Q12.
Write a function validate_record(record, schema) where schema is {'name': str, 'age': int, 'active': bool}. Return list of type mismatches.
Q13.
Write code that creates all falsy values in Python: 0, 0.0, 0j, '', [], (), {}, set(), None, False. Verify each with bool(). Then find a surprising truthy value.
Q14.
Write a function serialize(obj) that converts any Python object to a JSON-compatible type: sets→lists, tuples→lists, None→null. Handle nested structures.
Q15.
Write a function find_type_mismatches(list1, list2) that compares two lists element-by-element and reports positions where types differ.
Q16.
Write a function create_matrix(rows, cols, fill=0) that creates a 2D list correctly (no shallow copy trap). Demonstrate the trap with [[0]cols]rows.
Q17.
Write a function dict_diff(d1, d2) that returns: keys only in d1, only in d2, in both with same values, in both with different values.
Q18.
Write a function type_histogram(data) that counts occurrences of each type in a mixed list. Return {'int': 3, 'str': 2, 'float': 1}.
Q19.
Write code showing that tuples are hashable but lists are not. Create a dict mapping tuple-keys to values. Show the error with list-keys.
Q20.
Write a function smart_equals(a, b) that compares with type awareness: smart_equals(1, 1.0) → True but smart_equals(1, '1') → False.
Q21.
Write a function deep_freeze(obj) that recursively converts mutable types to immutable: lists→tuples, sets→frozensets, dicts→frozenset of tuples.
Q22.
Write a function type_coercion_chain(value, *types) that tries casting value through each type in sequence: type_coercion_chain('42.5', int, float) → 42.5.
Q23.
Write code that demonstrates string interning: a = 'hello'; b = 'hello'; print(a is b). Then try with a = 'hello world'. Explain the difference.
Q24.
Write a function build_schema(sample_data) that infers a schema from a list of dicts: {'name': 'str', 'age': 'int', 'scores': 'list'}. Handle inconsistent types.
Q25.
Write a function type_safe_merge(*dicts) that merges dicts but raises TypeError if the same key has different types across dicts.
📊 Day 1 Executive Summary
| # | Type | Focus Area | Professional Application |
|---|---|---|---|
| 1 | int | Topic 1 | Absolute counts, primary IDs |
| 2 | float | Topic 2 | Metrics, continuous variables |
| 3 | complex | Topic 3 | Scientific computing |
| 4 | str | Topic 4 | Text parsing, categorical data |
| 5 | bool | Topic 5 | Logic gating, boolean masks |
| 6 | list | Topic 6 | Ordered, mutable data streams |
| 7 | tuple | Topic 7 | Immutable constraints, fast read |
| 8 | set | Topic 8 | O(1) deduplication, set theory |
| 9 | dict | Topic 9 | Fast lookups, unstructured rows |
| 10 | None | Topic 10 | Explicit null-value handling |
✅ Instructor's End-of-Day Checklist
• [ ] I deeply understand the difference between mutable and immutable types.
• [ ] I know why evaluating set membership is faster than list membership.
• [ ] I understand the relationship between bool and int.
• [ ] I can safely handle NoneType values to prevent runtime errors.
• [ ] I have successfully completed all 5 practice tasks.
• [ ] I have reviewed and internalized all 25 interview questions.