Additional argument for str.join()

I’ suggesting an additional argument for str.join() so that

', '.join(['a', 'b', 'c'], ', or ')

would output

'a, b, or c' (sorry, I had an additional ‘,’ in my post at Issue 43280: additional argument for str.join() - Python tracker that was grammatically wrong and confusing)

The reason for this idea is that I often have functions where string arguments can have a finite number of different values and I’d like to have a quick way of give good feedback in ValueErrors, e.g.,

def do_something(method: str):
    methods = ['a', 'b', 'c']
    if method not in methods:
       raise ValueError(f"method is {method}, but has to be {', '.join(methods, ', or ')}") 

Might still be to specific, but I wanted to give it a shot.

1 Like

Consider the case where there are two items in the list: (as a non-native speaker,) “Has to be A, or B” doesn’t feel as good as “Has to be A or B” to me. I also suppose (again, not sure about that) there might be languages where the conventions for enumerations are different. At least, both of the message string and the additional ', or ' string have to be marked as translatable in an i18n context.

Overall, this looks too specific a use case for a core API in my admittedly uneducated eye.

If there is demand for this particular style of message formatting, why not a function somewhere in the standard library, e.g., in logging?

That being said, I would personally sacrifice a bit of eloquence here and say something along the lines of:

f"Method {method} not in allowed values: {', '.join(methods)}"

I am also cautiously skeptical that this use case is frequent. Take the open() function, for example.

>>> open("file", mode="invalid")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid mode: 'invalid'

That doesn’t list allowed modes, and I think this is because there are too many for sensibly listing in an error message. help(open) explains them.

2 Likes

Oh, see also this discussion: Full left and right "separator".join(L) - #3 by terrdavis

1 Like

Hi Fabian,

Can you think of any use for this new feature apart from joining a
comma-separated list of words with a conjunction (“or” or “and”) at the
end?

For example, is there a use for this with some other joiner:

':'.join(words, '-')

or similar?

This seems too specific to English to be made into a general purpose
string method.

2 Likes

We’re muddling ‘join’ and ‘format’ here. To my mind these are functions too different in type to be elegantly muddled.

I prefer an argument to ‘format’ that inserts a token into a list of strings – such as we have in this example – but even that is fraught.

Consider the Oxford comma. I am very strongly in favor of the Oxford comma, but I know some people who just as passionately abhor it. To keep us both happy, we’re going to need an extra flag or some tricky argument.

So no no no, I say. This is just the thing for a specific function for a particular class of application, but is not a candidate for the general string library.

1 Like

Many use cases could be handled by rewording the context.

>>> def do_something(method: str):
...     methods = {'a', 'b', 'c'}
...     if method not in methods:
...        raise ValueError(f"method {method} must be one of {methods}")
... 
...     
>>> do_something('d')
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    do_something('d')
  File "<pyshell#1>", line 4, in do_something
    raise ValueError(f"method {method} must be one of {methods}")
ValueError: method d must be one of {'b', 'c', 'a'}
>>>