So a bit late to the party, but let me just add my 2 cents. I agree with most of the comments above. Do add annotations, write good docstrings with doctesting und zu weiter.
Solution 1
However, I feel this code could have been written even more pythonic. My approach would be something like this
def comma_code(items: list[str], oxford_comma: bool = True) -> str:
"""Transforms ['a', 'b', 'c'] into 'a, b, and c' or 'a, b and c'"""
if not items:
return ""
*items_except_last, last_item = items
return (
", ".join(items_except_last)
# 'a and b' not 'a, and b' so we need 3 or more items for oxford comma
+ ("," if oxford_comma and len(items) >= 3 else "")
+ (" and " if items_except_last else "")
+ last_item
)
- Typing hints and a clear variable name.
string_2_list
is as generic of a name as they come. Avoid generic names and try to encompass the intent of your code through good function names and variables. Hence "comma_code" is a decent name, as this is the problem we are solving.
- Early returns so we avoid the arrow nesting problem
- The * operator unpacks an argument list. It allows you to call a function with the list items as individual arguments.
- Notice that we also avoid temporary strings everything is simply returned.
- The functionality is slightly expanded by introducing the oxford comma. When coding we need to be careful not over-engineering our solutions.
In the cases where we've considered things over engineered, it's
always been describing software that has been designed to be so
generic that it loses sight of the main task that it was initially
designed to perform, and has therefore become not only hard to use,
but fundamentally unintelligent.
- We avoid indices at all in our code, as some would consider them unpythonic. We refer to the number of items only once, and add a comment explaining that the oxford comma only comes into play when we have
3
or more elements.
- Again the code should have proper docstring and doctests, but the other commenters have already commented on this.. (And I am lazy).
Solution 2
If we wanted to write a more generic code, we could do it as follows.
def list_2_str_atbspw(
items: list[str], conjuction="and", seperator=",", spaces=True
) -> str:
if not items:
return ""
*items_except_last, last_item = items
return (
(seperator + (space := " " if spaces else "")).join(items_except_last)
+ (space + conjuction + space if items_except_last else "")
+ last_item
)
def comma_code(items: list[str], oxford_comma: bool = True) -> str:
return list_2_str_atbswp(
items,
seperator=",",
conjuction=", and" if oxford_comma and len(items) > 2 else "and",
)
Here we have separated the work of adding conjunctions and separators to its own function. Where "atbswp" is short for "Automate the Boring Stuff with Python". While I do like this code, I would not write it in production. Why? list_2_str_atbswp
is close to being a god object. If we use this function a lot and in many different situations it can make maintaining it difficult. If we change the input of list_2_str_atbswp
every function that uses this would also have to change.
Our original solution is more than good enough. The problem asked us to use comma in our code, so of course we are going to comma and not some other separator =P