Naming: prefer specific over generic. The function name tells us nothing about its behavior or purpose. Better alternatives could mention the idea of joining, punctuation, or the Oxford comma.
Naming: prefer ordinary over awkward. The function's argument could be
anything, so how do we name it? Not with something like l_list
: it's
needlessly awkward to type, visually off-putting, and tells us nothing more
specific than several ordinary or conventional alternatives: items
, vals
,
xs
, etc.
Duck typing: Python generally embraces it. Whenever feasible, avoid
imposing overly strict typing requirements on functions and methods. We don't
actually care whether the function's argument is a list or even a sequence. Any iterable of values
convertible to str
will work. Many data types satisfy our needs: list[str]
,
tuple[str]
, a dict
with str
keys, just a str
(of characters), or endless
user-defined objects.
Unnecessary quote marks. Your current code is adding single-quote marks to the returned string that I don't think are called for in the problem statement.
Simplifying the logic: fewer conditional branches. If there are 0, 1, or 2
values, you can just join them with ' and '
. Otherwise, you do the Oxford
comma routine -- which can be made more readable by popping off the last value.
Writing better demo code. It's great that you posted your question with a
main()
method to exercise your code. Even better would be to do the same
thing covering the primary input scenarios: 0 values, 1, 2, 3, and 4+. An
illustration is shown below. Better still would be a demo framed
as a test with assertions: I was too lazy for that, but we have
higher expectations for you!
def demo():
vals = ['A', 'B', 'C', 99]
for i in range(len(vals) + 1):
xs = vals[0:i]
gottext = oxford_comma_join(xs)
print(xs, gottext)
def oxford_comma_join(xs):
# Convert iterable to sequence of str.
try:
seq = [str(sx) for sx in xs]
except Exception:
raise ValueError
# Return joined str.
if len(seq) < 3:
return ' and '.join(seq)
else:
last = seq.pop()
return ', '.join(seq) + ', and ' + last
if __name__ == '__main__':
demo()