# Part 3: Python Collections - Quick Review for Experienced Developers

This document provides a quick reference to Python's advanced and specialized collection types from the `collections` module.

---

### 1. Sorting: `sort()` vs `sorted()`

- **`list.sort()`**: In-place sort. Modifies the original list and returns `None`.
  ```python
  my_list = [3, 1, 2]
  my_list.sort() # my_list is now [1, 2, 3]
  ```
- **`sorted()`**: Built-in function. Returns a *new* sorted list, leaving the original unchanged.
  ```python
  original_list = [3, 1, 2]
  new_list = sorted(original_list) # new_list is [1, 2, 3], original_list is unchanged
  ```

---

### 2. Tuple Unpacking

- **Basic Unpacking**:
  ```python
  a, b = (10, 20)
  ```
- **Extended Unpacking (`*`)**:
  ```python
  first, *middle, last = [1, 2, 3, 4, 5]
  # first -> 1
  # middle -> [2, 3, 4]
  # last -> 5
  ```

---

### 3. Specialized Collections in `collections`

A brief overview of useful classes in the `collections` module.

| Class | Description | Common Use Case |
| :--- | :--- | :--- |
| `Counter` | A `dict` subclass for counting hashable objects. | Counting item frequencies, finding most common items. |
| `defaultdict`| A `dict` subclass that calls a factory function for missing keys. | Grouping items into lists or other collections without checking for key existence. |
| `deque` | "Double-ended queue". Fast appends and pops from both ends. | Implementing queues, stacks, or keeping a list of "last N" items. |
| `namedtuple` | Factory function for creating tuple subclasses with named fields. | Creating simple, immutable objects with attribute access for better readability. |

---

### 4. Code Examples

- **`Counter`**:
  ```python
  from collections import Counter
  counts = Counter(['a', 'b', 'a', 'c', 'a'])
  # Counter({'a': 3, 'b': 1, 'c': 1})
  print(counts.most_common(1)) # [('a', 3)]
  ```
- **`defaultdict`**:
  ```python
  from collections import defaultdict
  s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4)]
  d = defaultdict(list)
  for k, v in s:
      d[k].append(v)
  # defaultdict(<class 'list'>, {'yellow': [1, 3], 'blue': [2, 4]})
  ```
- **`deque`**:
  ```python
  from collections import deque
  last_five = deque(maxlen=5)
  for i in range(10):
      last_five.append(i)
  # deque([5, 6, 7, 8, 9], maxlen=5)
  ```
- **`namedtuple`**:
  ```python
  from collections import namedtuple
  Point = namedtuple('Point', ['x', 'y'])
  p = Point(11, y=22)
  print(p.x, p.y) # 11 22
  ```

---
For more detailed explanations and examples, please see the main [part_3_python_collections.md](./part_3_python_collections.md) document. 