Skip to main content
added 2 characters in body
Source Link
FMc
  • 12.8k
  • 2
  • 28
  • 40

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()

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]
        got = oxford_comma_join(xs)
        print(xs, got)

def oxford_comma_join(xs):
    # Convert iterable to sequence of str.
    try:
        seq = [str(s) for s 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()

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]
        text = oxford_comma_join(xs)
        print(xs, text)

def oxford_comma_join(xs):
    # Convert iterable to sequence of str.
    try:
        seq = [str(x) for x 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()
Source Link
FMc
  • 12.8k
  • 2
  • 28
  • 40

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]
        got = oxford_comma_join(xs)
        print(xs, got)

def oxford_comma_join(xs):
    # Convert iterable to sequence of str.
    try:
        seq = [str(s) for s 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()