Playlist class implementing __len__ and __getitem__ so len(p), p[0], negative indexing and even for song in p all work — implementing __getitem__ alone is enough to make an object iterable.p = Playlist(['a', 'b']); (len(p), p[-1])
(2, 'b')
Both dunders delegate to the wrapped list.
return self._songs[index] handles negatives free of charge.
Iteration falls back to __getitem__ with 0, 1, 2, …