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.
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.
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.
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'}
>>>