# Is there a simpler way to make an English-readable list from strings in a tuple?

I looking over some old code, I had written the function below with a C-style for-loop iterating over a count variable. I then fixed it up with new knowledge, but still am suspicious that there is even a better way to do this.

The function should behave like so:

>>> join_list(['a'])
'a'
>>> join_list(['a', 'b'])
'a or b'
>>> join_list(['a', 'b', 'c'])
'a, b, or c'


The function I have currently:

def join_list(my_list):
length = len(my_list)
if length == 1:
return my_list[0]
elif length == 2:
return ' or '.join(my_list)
else:
head = ', '.join(my_list[:-1])
return head + ', or ' + my_list[-1]

• There's no docstring! – Gareth Rees Feb 8 '14 at 10:28
• To be fair I defined this function within my if __name__ == '__main__' conditional, but I digress I think the code speaks for itself :). – Winny Feb 8 '14 at 17:34

Looks pretty good. The only problem I can see is that you're not doing a check to make sure the list is not empty: if it is, then you'll try to access my_list[-1] in the final else clause, which will raise an IndexError.

Hence, I'd simply add a check up front for length == 0 and return '' in that case.

• if you handle 2 and 3 item cases first you can fall through to ''.join(my_list) which covers both 0 and 1 – theodox Feb 8 '14 at 17:41
• I like that a lot, but I want to test for least first. All I need to change is the first clause to if length <= 1: ''.join(my_list) – Winny Feb 8 '14 at 18:06

You could also write, a bit shorter:

def join_list(items):
if not items:
return ''
*init, last = map(str, items)
return (', '.join(init) + ' or '*bool(init) + last)


Example:

>>> join_list(range(5))
'0, 1, 2, 3 or 4'

• I tested that on Python 2.7.6 and Python 3.3. Looks like the asterisk in *init, last = map(str, items) raises a SyntaxError on Python 2.7.6. Do you know what that feature of Python 3.3 is called? – Winny Feb 9 '14 at 4:49
• @Winny Sorry, forgot to mention its python3 code. Its called extended unpacking (pep 3132). – Lennart_96 Feb 10 '14 at 9:09