q&a

Python Basics

Python Fundamentals

  • Data types, Variables, Scope

  • Immutable vs Mutable Objects

Immutable Objects

  • Cannot be changed after creation. Any modification creates a new object.

  • Examples:

    • Numbers: int, float, complex

    • Strings: str

    • Tuples: tuple

    • Frozen Sets: frozenset

  • Immutability Example:

    x = "hello"
    x = x + " world"  # Creates a new string
    print(x)  # Output: 'hello world'
  • Explanation: Strings are immutable; concatenation creates a new string rather than modifying the original.

Mutable Objects

  • Can be changed in place without creating a new object.

  • Examples:

    • Lists: list

    • Dictionaries: dict

    • Sets: set

    • User-defined objects (if attributes are modifiable)

  • Mutability Example:

    lst = [1, 2, 3]
    lst.append(4)  # Modifies the list in place
    print(lst)  # Output: [1, 2, 3, 4]

Key Differences

Feature

Mutable Objects (e.g., List)

Immutable Objects (e.g., String)

Can be changed in place?

✅ Yes

❌ No

Uses new memory on modification?

❌ No

✅ Yes

Examples

list, dict, set

int, str, tuple

Implications of Mutability

  1. Performance Considerations:

    • Frequent changes to immutable objects can be inefficient.

  2. Safety in Multi-threading:

    • Immutable objects prevent accidental modifications, making them safer.

  3. Dictionary Keys & Set Elements:

    • Only immutable objects can be used as keys in dictionaries or elements in sets.

Examples of Valid and Invalid Keys:

# Valid dictionary keys
 d = { (1, 2): "valid" }
 frozenset([4, 5]): "frozenset key"

# Invalid keys
 d = { [1, 2]: "list key" }  # TypeError
 d = { {3: 4}: "dict key" }  # TypeError

The Role of hash and eq

  1. __hash__:

    • Returns a unique integer representing the hash value of an object.

    • Required for objects to be used as dictionary keys or set elements.

    • Example: hash(42).

  2. __eq__:

    • Defines equality between objects and is used for checking if different objects have the same hash value.

class CustomKey:
    def __init__(self, value):
        self.value = value
    def __hash__(self):
        return hash(self.value)
    def __eq__(self, other):
        return isinstance(other, CustomKey) and self.value == other.value

# Dictionary using custom objects as keys
 d = {CustomKey(10): "value1"}