Mental model: Think of a list as a tray holding distinct cards in order. Some tools let you grab all the cards and lay them out neatly on a new table (sorting), while others rearrange the cards right where they sit, changing that same tray.
Why it matters: Real programs constantly need to rank results. When you build a leaderboard for game scores or order sensor readings from coldest to hottest, these built-in tools do the heavy lifting so your logic stays clean and readable.
Sorting without side effects
sorted() returns a brand-new list in order, leaving the original untouched. The .sort() method rearranges your existing list right there and does not return anything new.nums = [3, 1, 4]
# sorted() gives a NEW list; nums stays the same
new_nums = sorted(nums)
print(new_nums) # [1, 3, 4]
print(nums) # [3, 1, 4] (unchanged!)
nums.sort()
print(nums) # [1, 3, 4] (modified in place)The first call gave us a sorted copy while keeping the original order safe. The second method rearranged
nums directly because we did not need the old sequence anymore.Descending sort
scores = [85, 92, 78]
print(sorted(scores)) # ascending by default: [78, 85, 92]
print(sorted(scores, reverse=True)) # descending: [92, 85, 78]The
reverse flag flips the direction so the largest values appear first. This is exactly what you need when ranking scores from highest to lowest.Built-in aggregations and lookups
temps = [41, 39, 52, 60]
print(min(temps)) # lowest value: 39
print(max(temps)) # highest value: 60
print(sum(temps)) # total: 192min, max, and sum scan the list once to give you those three key statistics. You can compute them directly without writing a loop.fruits = ['apple', 'banana', 'apple']
print(fruits.count('apple')) # how many times it appears: 2
print(fruits.index('banana')) # first position of that item: 1count tells you frequency, while index finds the very first spot where a specific item lives in your sequence.Copying a list safely
# Without a copy, both names point to the SAME object
a = [10, 20]
b = a # b is just another name for a's list!
b.append(30)
print(a) # [10, 20, 30] -- oops! we changed 'a' too.
# Make an independent copy instead
c = [40, 50]
d = c.copy() # .copy() hands back a brand new list
d.append(60)
print(c) # [40, 50] -- untouched
The first block shows that assigning one variable to another does not make a duplicate: both names point at the same list, so a change through either one shows up in both. The second block uses
.copy() to build a genuinely separate list that you can modify without touching the original.