Dunder names are reserved for use by the Python interpreter.
That's convenient, because my suggestion is to add a magic attribute into the Python specifications ;) It would be a `type` attribute, like `__mro__` or others.
So here we have `__attrs__` is not just a dunder attribute, but also a dunder built-in name.
It hasn't to be a built-in name in global scope but only in the scope of class declaration (and could then be interpreted by type checkers has being owned by the class being declared). Using it outside a class declaration should raise a `NameError`.
By the way, I think you did not understand my suggestion, so maybe it was not enough clear — that's maybe related too to the fact you precise in an other post that your are "not aware of many refactoring tools for Python at all".
So I will develop my point by talking about an other pseudo-static (but completely dynamic under the hood) standard Python feature; let's talk about dataclasses. Dataclasses are a dynamic thing, a decorator which rewrite class methods; this is so dynamic that the method code is first written as a string and then compiled with `exec`, and that it use regex parsing under the hood to check types in stringified annotations. That's under the hood. However, for the user, thanks to IDEs, type checkers, linters, etc. this is handled as a static feature. Attribute access can be type checked, and `__init__` method parameters are checked too. Don't believe that IDEs and other tools execute the `dataclass` code for each class in order to retrieve the signature of the generated method. No, they just compute it themselves statically, because they **know that it will be generated this way**. How do they know ? Because it's written in Python specifications, so they have to handle it. And if you write code reassigning an attribute of a frozen dataclass, linter will warn you, while the real check is dynamic and realized in class generated `__setattr__`. (To prove you that's purely static, try to do `dataclass2 = dataclass` and execute mypy with a class decorated by `dataclass2`)
So, if tools are able to statically compute a signature of dataclass `__init__` by using its fields annotations (even if it's dynamic like hell behind), I hope you begin to understand how they could be able to interpret `__attrs__.bar` in a different manner than raw `"bar"`; it's not "one more step" as you said, it's a different processing, and because it's a different processing, type checking can be added, using for example my suggested `_SpecialForm` `Attribute[Owner, T]`
So linters that cannot cope with `@validate('email')` will be able to cope with `@validate(__attrs__.email)`, because ... why?
Because it would be written in Python specification that this has a special meaning for type checking, as it is for dataclasses methods. That's why I dare use a dunder name, because it's a suggestion for the Python specification.
Presumably these would work too: `assert getattr(foo, None.__attrs__.bar) == 0` `assert getattr(foo, foo.__attrs__.baz, 999) == 999`
It will works, yes, but the same way that passing a `str` to a function annotated with an `int` parameter: type checker will shout at you. Python static checks are never enforced dynamically, this suggestion does not aim to change this behavior.
But in Python, dynamics things can be interpreted in a static way by tools, they needs a specification to follow, dataclasses being again the best example.
Apart from typing 15 chars to avoid 2 quotation marks, and making a runtime attribute lookup plus method call to avoid a literal, how will this help reduce dynamicism?
I hope that you've understood now with this complementary explanation (and yes, there is more chars typed, but is that an issue when meanings are different?)