A Python list is an ordered sequence that can retain repeated values. That makes it a natural baseline for collected data, but not necessarily the best structure for every operation. Profile the operation that matters before replacing it: exact membership, interval search, and memory use favor different choices. section 2.3 section 2.3.3
Repeated temperature lookup
A station’s temperature list contains 141,082 readings. Converting it with `set(first_all_temperatures)` leaves 400 distinct values; timed exact-membership checks against the set take tens of nanoseconds. Much of this gain comes from removing duplicates. Conversion is useful when repeated searches need only to establish whether a value occurred, rather than preserve the full sequence. section 2.3 section 2.3.2
Duplicate removal is not the whole explanation. With 100,000 distinct integers in both a list and a set, timed searches still favor the set: list membership takes hundreds of microseconds, versus tens of nanoseconds for the set. CPython sets use hashes for lookup. Keep an ordered list when searching an interval, however: bisection can locate its start, after which the list can be traversed until the interval ends. section 2.3.3
a_list_range = list(range(100000)) a_set_range = set(a_list_range) %timeit 50000 in a_list_range %timeit 50000 in a_set_range %timeit 500000 in a_list_range %timeit 500000 in a_set_range
Run the list-versus-set membership benchmark with distinct values to separate lookup behavior from the effect of removing duplicates. section 2.3.3
Measure memory with the same care. `sys.getsizeof(a_list)` reports the list container, not everything its entries refer to. In a file-data example, a list of 1,303,981 entries reports 10,431,904 bytes before accounting for its elements. A whole-file string instead reports 1,304,030 bytes. Compare representations against the access pattern as well as the container size; a single shallow size measurement is not the total footprint. section 2.4.1 section 2.4.2




















