Python Data Types


Python Data Types Interview with follow-up questions

1. Can you explain the different data types available in Python?

Python's built-in data types, with examples:

  • int — whole numbers of arbitrary precision (no overflow), e.g. 42, 10**100
  • float — double-precision decimals, e.g. 3.14; complex for complex numbers, e.g. 2 + 3j
  • boolTrue/False (technically a subclass of int)
  • str — immutable Unicode text, e.g. "hello"; bytes/bytearray for raw binary
  • list — mutable ordered sequence, e.g. [1, 2, 3]
  • tuple — immutable ordered sequence, e.g. (1, 2, 3)
  • range — a lazy integer sequence, e.g. range(10)
  • dict — key/value mapping, insertion-ordered since 3.7, e.g. {"name": "Ada", "age": 36}
  • set / frozenset — unique hashable items, e.g. {1, 2, 3}
  • NoneType — the single value None

The follow-ups that separate juniors from seniors:

  • Mutability: list, dict, set, bytearray are mutable; int, float, str, tuple, frozenset, bytes are immutable. This drives the mutable-default-argument bug and copy-vs-reference behavior.
  • Hashability: only hashable (usually immutable) objects can be dict keys or set members.
  • Everything is an object; a variable is a name bound to one, so assignment never copies. Check types with isinstance(x, ...), and annotate with list[int], dict[str, int], etc.
↑ Back to top

Follow-up 1

What is the difference between a list and a tuple?

The main difference between a list and a tuple in Python is that a list is mutable, meaning its elements can be modified, added, or removed, while a tuple is immutable, meaning its elements cannot be modified once it is created. Another difference is that a list is defined using square brackets [], while a tuple is defined using parentheses ().

For example:

my_list = [1, 2, 3]
my_tuple = (1, 2, 3)

my_list[0] = 4  # Modifying a list element
print(my_list)  # Output: [4, 2, 3]

my_tuple[0] = 4  # Error: 'tuple' object does not support item assignment

Follow-up 2

How can you convert a list to a tuple and vice versa?

To convert a list to a tuple, you can use the tuple() function, which takes an iterable (such as a list) as an argument and returns a tuple containing the same elements.

For example:

my_list = [1, 2, 3]
my_tuple = tuple(my_list)
print(my_tuple)  # Output: (1, 2, 3)

To convert a tuple to a list, you can use the list() function, which takes an iterable (such as a tuple) as an argument and returns a list containing the same elements.

For example:

my_tuple = (1, 2, 3)
my_list = list(my_tuple)
print(my_list)  # Output: [1, 2, 3]

Follow-up 3

What is a dictionary in Python?

A dictionary in Python is an unordered collection of key-value pairs. Each key is unique within the dictionary and is used to access its corresponding value. Dictionaries are defined using curly braces {} and key-value pairs are separated by colons :.

For example:

details = {'name': 'John', 'age': 25, 'city': 'New York'}
print(details['name'])  # Output: 'John'
print(details['age'])  # Output: 25
print(details['city'])  # Output: 'New York'

You can add, modify, or remove elements from a dictionary using various methods and operations.

Follow-up 4

How can you add and remove elements from a dictionary?

To add an element to a dictionary, you can use the square bracket notation and assign a value to a new or existing key.

For example:

details = {'name': 'John', 'age': 25}
details['city'] = 'New York'  # Adding a new key-value pair
print(details)  # Output: {'name': 'John', 'age': 25, 'city': 'New York'}

To remove an element from a dictionary, you can use the del keyword followed by the key you want to remove.

For example:

details = {'name': 'John', 'age': 25, 'city': 'New York'}
del details['age']  # Removing a key-value pair
print(details)  # Output: {'name': 'John', 'city': 'New York'}

Follow-up 5

What is the use of the set data type in Python?

The set data type in Python is used to store an unordered collection of unique elements. Sets are defined using curly braces {} or the set() function.

Sets are useful when you want to store a collection of items without any duplicates and perform mathematical set operations such as union, intersection, and difference.

For example:

my_set = {1, 2, 3}
print(my_set)  # Output: {1, 2, 3}

my_set.add(4)  # Adding an element to a set
print(my_set)  # Output: {1, 2, 3, 4}

my_set.remove(2)  # Removing an element from a set
print(my_set)  # Output: {1, 3, 4}

2. How is memory managed for different data types in Python?

CPython manages memory automatically through two mechanisms working together:

  1. Reference counting (primary): every object carries a count of how many names/containers reference it. The count rises on each new binding and falls when a reference goes away; when it hits zero, the object is freed immediately and deterministically.

  2. Cyclic garbage collector (backup): reference counting alone can't reclaim reference cycles (e.g. a.ref = b; b.ref = a — each keeps the other's count above zero even when nothing else points to them). A generational GC, in the gc module, periodically detects and collects these unreachable cycles.

Details that come up as follow-ups:

  • Small-object optimizations: CPython caches small integers (−5 to 256) and interns short strings, so a = 256; b = 256 may share one object (a is b is True), while 257 may not — a classic is vs == gotcha. Use == for value equality, is only for identity (especially is None).
  • The reference-counting model is also why the GIL existed — making refcounts thread-safe without per-object locks. The free-threaded build in Python 3.14 reworks this.
  • Memory is requested from the OS via CPython's pymalloc arena allocator, not malloc per object.

So: refcounting handles the common case promptly, and the cyclic GC sweeps up what refcounting can't.

↑ Back to top

Follow-up 1

How does Python handle memory allocation for mutable data types?

For mutable data types like lists and dictionaries, Python uses dynamic memory allocation. When you create a mutable object, Python allocates memory to store the object's data. As you modify the object, Python may need to allocate additional memory to accommodate the changes. Python also automatically deallocates memory when an object is no longer needed.

Follow-up 2

What happens when you modify an element of a tuple?

Tuples are immutable in Python, which means you cannot modify their elements. If you try to modify an element of a tuple, you will get a TypeError indicating that tuples do not support item assignment. If you need to modify the contents of a collection, you should use a mutable data type like a list instead.

Follow-up 3

How does Python manage memory for large lists or dictionaries?

When dealing with large lists or dictionaries, Python's memory management works the same way as for smaller objects. However, the memory usage can be more significant due to the size of the data. If memory becomes a concern, you can consider using more memory-efficient data structures or algorithms, or processing the data in smaller chunks to reduce the memory footprint.

3. What are the mutable and immutable data types in Python?

Mutable types can be changed in place after creation; immutable types cannot — any "change" produces a new object.

  • Mutable: list, dict, set, bytearray — you can add, remove, or reassign elements.
  • Immutable: int, float, complex, bool, str, tuple, frozenset, bytes, and None.
nums = [1, 2, 3]
nums[0] = 99          # fine — lists are mutable

name = "Ada"
name[0] = "X"         # TypeError — strings are immutable
name = name.replace("A", "X")  # makes a NEW string instead

Why interviewers care — the real gotchas:

  • Mutable default arguments: def f(items=[]) shares one list across all calls. Use None as a sentinel and build the list inside the function.
  • Aliasing: assignment binds a name, it doesn't copy. b = a on a list means mutating b also changes a; use a.copy() or copy.deepcopy() when you need independence.
  • Hashability: only immutable (hashable) objects can be dict keys or set members — that's why you can't put a list in a set but you can a tuple.
  • A "frozen" gotcha: a tuple is immutable, but a tuple containing a list still lets you mutate that inner list — immutability is shallow.
↑ Back to top

Follow-up 1

Why are some data types in Python mutable and others are not?

The mutability or immutability of a data type in Python is determined by its design and purpose.

Mutable data types are designed to be modified because they often represent collections of elements that can change over time. For example, a list can have elements added or removed, and a dictionary can have key-value pairs modified or deleted.

On the other hand, immutable data types are designed to be constant and unchangeable. This can be useful in situations where you want to ensure that a value remains the same throughout the program execution, such as when using a string to store a password or a tuple to represent a coordinate.

Follow-up 2

Can you give an example of a situation where it would be beneficial to use an immutable data type?

One example of a situation where it would be beneficial to use an immutable data type is when you want to use a value as a key in a dictionary.

Since dictionary keys must be unique, using an immutable data type like a string or a number ensures that the key remains constant and cannot be accidentally modified. This helps maintain the integrity of the dictionary and prevents unexpected behavior.

For example, consider a dictionary that stores information about students, where the keys are their student IDs. By using immutable data types for the keys, you can ensure that each student ID remains constant and unique.

Follow-up 3

What are the implications of mutability on Python's memory management?

The mutability of data types in Python has implications on memory management.

When a mutable object is modified, Python may need to allocate additional memory to accommodate the changes. This can lead to increased memory usage and potentially slower performance.

On the other hand, immutable objects do not require additional memory allocation when their values are modified. Instead, a new object is created with the updated value, and the old object is garbage collected.

This difference in memory management can be important when working with large data sets or in performance-critical applications.

4. How can you perform operations like addition, deletion, and search on Python data types?

Each built-in type exposes operators and methods for add/delete/search. The common ones:

# Lists
items = [1, 2, 3]
items.append(4)        # add to end; insert(i, x) for a position
items.remove(2)        # delete by value (first match); del items[0] by index
items.pop()            # remove + return last
3 in items             # membership test (search)
items.index(3)         # find position (raises ValueError if absent)

# Dicts
d = {"a": 1}
d["b"] = 2             # add / update by key
del d["a"]             # delete by key
d.pop("b", None)       # delete with a default if missing
"b" in d               # membership tests KEYS, not values
d.get("x", 0)          # safe lookup with a default

For sets: add(), discard() (no error if absent) or remove() (raises), and x in s for membership.

Follow-ups about complexity — the part interviewers actually want:

  • dict and set lookups, insertions, and deletions are O(1) on average (hash table); membership in a list is O(n) because it scans. If you're repeatedly checking x in big_list, convert to a set.
  • list.index() and list.remove() are O(n); append/pop() from the end are amortized O(1), but insert(0, x) / pop(0) are O(n) — use collections.deque for fast front operations.
  • Indexing a missing dict key raises KeyError; prefer .get() or collections.defaultdict when a default is expected.
↑ Back to top

Follow-up 1

How can you add an element to a list or a dictionary?

To add an element to a list, you can use the append() method. Here's an example:

my_list = [1, 2, 3]
my_list.append(4)
print(my_list)  # Output: [1, 2, 3, 4]

To add an element to a dictionary, you can use the square bracket notation. Here's an example:

my_dict = {'key1': 'value1', 'key2': 'value2'}
my_dict['key3'] = 'value3'
print(my_dict)  # Output: {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}

Follow-up 2

How can you delete an element from a list or a dictionary?

To delete an element from a list, you can use the remove() method. Here's an example:

my_list = [1, 2, 3, 4]
my_list.remove(3)
print(my_list)  # Output: [1, 2, 4]

To delete an element from a dictionary, you can use the del keyword. Here's an example:

my_dict = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
del my_dict['key2']
print(my_dict)  # Output: {'key1': 'value1', 'key3': 'value3'}

Follow-up 3

How can you search for an element in a list or a dictionary?

To search for an element in a list, you can use the index() method. Here's an example:

my_list = [1, 2, 3, 4]
index = my_list.index(3)
print(index)  # Output: 2

To search for an element in a dictionary, you can use the square bracket notation to access the value associated with a specific key. Here's an example:

my_dict = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
value = my_dict['key2']
print(value)  # Output: 'value2'

5. What are the methods associated with Python data types like list, tuple, dictionary, and set?

Common methods per type:

List (mutable, ordered):

  • append(x) / extend(iterable) / insert(i, x) — add
  • remove(x) / pop([i]) / clear() — delete
  • index(x) / count(x) — search
  • sort() (in place) / reverse() / copy()

Tuple (immutable): only count(x) and index(x) — no methods mutate it.

Dict (insertion-ordered):

  • keys() / values() / items() — return live views, not lists
  • get(k, default) / setdefault(k, default)
  • update(other) / pop(k[, default]) / popitem() — note popitem() removes the last inserted pair (LIFO since 3.7)
  • dict1 | dict2 merges (3.9), |= updates in place

Set (unique items):

  • add(x) / remove(x) (raises if absent) / discard(x) (silent) / pop() (arbitrary element)
  • union()/|, intersection()/&, difference()/-, symmetric_difference()/^

Follow-ups interviewers expect:

  • sort() vs sorted(): sort() mutates the list and returns None; sorted(iterable) returns a new list and works on any iterable. Same for list.reverse() vs reversed().
  • dict views are dynamic — they reflect later changes to the dict and aren't subscriptable; wrap in list(...) if you need a snapshot or indexing.
  • Methods that mutate (append, sort, add) return None, so x = mylist.sort() is a classic bug.
↑ Back to top

Follow-up 1

Can you explain the use of the append method in a list?

The append() method is used to add an element to the end of a list. It takes a single argument, which is the element to be added. Here's an example:

my_list = [1, 2, 3]
my_list.append(4)
print(my_list)  # Output: [1, 2, 3, 4]

Follow-up 2

How can you sort a list in Python?

To sort a list in Python, you can use the sort() method. By default, it sorts the list in ascending order. Here's an example:

my_list = [3, 1, 4, 2]
my_list.sort()
print(my_list)  # Output: [1, 2, 3, 4]

If you want to sort the list in descending order, you can pass the reverse=True argument to the sort() method:

my_list = [3, 1, 4, 2]
my_list.sort(reverse=True)
print(my_list)  # Output: [4, 3, 2, 1]

Follow-up 3

What is the use of the keys method in a dictionary?

The keys() method in a dictionary is used to return a list of all the keys in the dictionary. Here's an example:

dictionary = {'name': 'John', 'age': 25, 'city': 'New York'}
keys = dictionary.keys()
print(keys)  # Output: ['name', 'age', 'city']

You can then use this list of keys to perform various operations on the dictionary, such as accessing the values associated with the keys or iterating over the key-value pairs.

Follow-up 4

How can you remove duplicates from a list using a set in Python?

To remove duplicates from a list in Python, you can convert the list to a set and then convert it back to a list. Since sets cannot contain duplicate elements, this process effectively removes the duplicates. Here's an example:

my_list = [1, 2, 3, 2, 4, 1, 5]
my_list = list(set(my_list))
print(my_list)  # Output: [1, 2, 3, 4, 5]

Note that this method does not preserve the original order of the elements in the list. If you need to preserve the order, you can use the OrderedDict class from the collections module:

from collections import OrderedDict

my_list = [1, 2, 3, 2, 4, 1, 5]
my_list = list(OrderedDict.fromkeys(my_list))
print(my_list)  # Output: [1, 2, 3, 4, 5]

6. What is the difference between `is` and `==`, and what is interning?

A classic gotcha question. == compares values (calls __eq__); is compares identity (whether two names point to the same object in memory).

a = [1, 2]; b = [1, 2]
a == b   # True  — equal contents
a is b   # False — different objects

The trap interviewers set: small-integer and short-string interning.

x = 256; y = 256;  x is y   # True  — small ints (-5..256) are cached
x = 257; y = 257;  x is y   # often False — outside the cached range

Key rules: use == for value comparison; reserve is for singletons — is None, is True, is False (never == None). Relying on is for integers/strings is a bug because interning is an implementation detail (and behaves differently in the REPL vs a script, where the compiler may fold constants). Follow-up: __eq__ and __hash__ must stay consistent for objects used as dict keys / set members.

↑ Back to top

Live mock interview

Mock interview: Python Data Types

Intermediate ~5 min Your own free AI key

Your voice and your AI key never touch our servers; the key stays in this browser and is sent only to Google. Only your round scores are saved to track progress.