Because I’m programmatically creating forms based on dataclasses, and in some cases I want to have a different class name to the name displayed on the form.
… although now you mention it maybe I should just treat it as a localization problem.
I think this is a bit too niche for the standard library. Even if dataclass() supported something like str="...", I would expect it to affect the instance’s __str__, not the class. Personally, I’d just use a ClassVar here:
from dataclasses import dataclass
from typing import ClassVar
@dataclass
class Address:
label: ClassVar[str] = "An Address"
x: int
y: int
print(Address.label) # An Address
Address(1, 2) # Address(x=1, y=2)
It’s a bit more typing to access .label, but it feels cleaner than using a metaclass, which seems like overkill.
And it will never be with the semantics you are suggesting. I am saying this with a 99% certainty. It’s too niche of a feature, to weird of a behavior. No other class in the stdlib has anything close to this (except the typing “classes”, but those are a very different edge case). In third party libraries I can’t think of any examples either. If I saw something like this in code I had to review, I would reject it. Use a ClassVar, as already suggested.
This is not relevant to the issue at hand. Creating class variables does not require annotations, and this is not a question about typing. It’s like saying ‘annotate the variable as an int’ instead of simply ‘use an integer.’
Do lambdas as arguments for dataclass attributes work? If so, doing
from dataclass import dataclass
@dataclass
class Address:
__str__: Callable[[type[Address]], str] = lambda cls: "An Address"
could work, although I think the __str__ would probably rather be invoked for instances. I’d still give it a try.
If the str(Address) part is only needed for internal code, some attribute like __internal_string__ could also easily be used, in conjunction with getattr(obj, "__internal_string__", str(obj)) if you don’t know wether the object is a Address (or other similar dataclasses).