Alex Hall writes:
Do you not usually refactor duplicated code?
Taking "you" as generic: it depends.
What *do* you refactor?
Code is expressive. In cases where the duplication results in equivalent objects, I habitually refactor. When the process is important to express and the duplication is syntactic, I will prefer an explicit but idiomatic syntax repeated in unrelated contexts. Thus I generally wouldn't consider your list to be "duplicated code that cries out for refactoring." When the process is complex then I'd refactor. Detecting an out of bounds index is complex enough because of fenceposts and negative indicies, although I probably wouldn't notice the negative indicies until they bit me (and in that case wouldn't refactor until bitten).
I'd find it more interesting if there were a larger variety of cases
This sort of sounds like the problem. The examples aren't meant to be interesting.
"You [both] keep using that word but I do not think [Steven] means what you think it means." (pace, Inigo) I find the long list of examples with mostly identical syntax *unpersuasive* for two reasons. First, if you're going to bounds check array indicies explicitly (rather than allow IndexError to "bubble up"), we already have a facility for doing that precisely and accurately: catch IndexError. That catches out of bounds indicies and nothing else[1], and it handles negative indicies correctly. list.get can't be implemented much more efficiently than by using try ... except IndexError, and invoking it imposes attribute lookup and function call overhead so I guess you net approximately nothing on time, and a little bit of space. If you care so much about either time or space, you'd implement inline, something like: value = lst[index] if - (N := len(lst)) <= index < N else default try ... except IndexError is TOOWTDI now, it's as readable as .get and more readable than the inline version, so introducing list.get would be redundant. Second, I can see why people would want it (see my reply to MAL), I just don't want it myself, and implementing your own *correctly* as a function is trivial: def get(container, subscript, default): try: return container[subscript] except (IndexError, KeyError): return default It follows that I think dict.get is a YAGNI, at least since the introduction of KeyError, and definitely now that we can write y = mydict[x] if x in mydict else default Footnotes: [1] It turns out that slice bounds can't be out of bounds, they simply get truncated, in the degenerate case to the empty slice.