If you find yourself requiring to include the repr and type of an object in an error message, what is stopping you from using a function like below?
from typing import Any
def describer(obj: Any) -> str:
return f'{repr(obj)} of type {type(obj).__name__}'
a = 1
if not isinstance(a, str | tuple):
print(f'{describer(a)} is not a string or tuple')
Python already has enough special symbols for strings. This proposal would add nothing of value and would just confuse users with new syntax.
Personally, I just keep a couple of functions around: r(obj) which
returns f'{type(obj).__name__}:{obj!r}' and a similar s(obj) which
uses str instead of repr. Then I can just use {r(obj)} as desired.
I generally don’t care about the variable name - that will often be
obvious in the code, and I can always mention it if it seems useful.
So I just go:
from cs.lex import r, s
and get on with my life.
I would not be in favour of a bunch of special purpose format thingies.
There’s too many tiny things we’d all bikeshed about and it is pretty
easy to roll things which get you 90% of the way there.
E.g. function argument name is the name of the variable, but it is reported in error messages.
Also, refactoring will change the variable name and error message will change with it, I don’t see what is wrong with it as long as it is a sensible variable name to report.
Also, the end user of software will never see these messages anyway. This is for low level code, which ideally should be as performant as possible.
Thus, writing complicated wrappers for these is not an option as it is often used in frameworks that extensively make use of error catching.
But this is my case and I can always make optimal compromise with existing features. And it is going to be ok. But with this it could be simpler and faster. So just thought maybe it could be of help to others too.
I realise now that it is a bit much - 1 function call and 1 method call. Nevertheless, I think this might be in at least top 5 of most used constructs in string formatting.
Of course one can write {type(var).__name__}:{var} or use a helper, but take a look from the opposite perspective. People don’t do that every time they should. Introducing any short and easy way for printing the type could help to create “the one and obvious way” to print an offending variable in all messages like this:
I really like this proposal. The type(...).__name__ is used a lot. According to GitHub search results, it’s used 1.23 times more than !r and 8.14 times more than !a, so I think !t is worth it.
Isn’t writing f"{type(var).__name__}:{var}" or using a helper function already obvious though? I think most IDEs would allow developers to infer that the dunder name attribute is the name of a type. Even if the attribute wasn’t too intuitive, couldn’t one also write `f"{var=} of {type(var}“, which is equivalent to f”{var=} of <class ‘{type(a).name}’>". If some developers didn’t see the benefits of using the obvious solutions, they wouldn’t use the less obvious solution that is the proposed syntax. I also think that the developers who found they needed such solutions would find using functions and/or f-string expressions, the pre-existing solutions, to be more obvious than using some new specialized syntax.
I suppose that expression is also another obvious, socially established option. You’re correct in saying that my argument questions the ! syntax. The expression also strengthens my argument, which is that the proposed ! syntax currently doesn’t have a lot of usecases because they’re already taken up by the more obvious, socially established solutions.