On Mon, 2021-12-13 at 09:57 +1100, Steven D'Aprano wrote:
> On Sun, Dec 12, 2021 at 12:48:36PM -0800, Paul Bryan wrote:
> 
> > But what's being annotated, the type or the attribute?
> 
> That's easy to test:
> 
> 
> > > > class A:
> ...     attr: Annotated[int, "Doc string"]
> ... 
> > > > int.__annotations__
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> AttributeError: type object 'int' has no attribute '__annotations__'
> 
> 
> Okay, so it's not the type. *wink*

OK, so it's not the type, except it kind of is. In my other example, I
used `Annotated` to create what I guess is (and what you suggested) a
pseudo-type? When it was annotated it had nothing to do with any
attribute. To reiterate:

SomeType = Annotated[str, "some type"]

No attribute here (yet). Only when this is applied as a type hint to an
attribute would it then apply.

class A:
    attr: SomeType

`Annotated` certainly appears to be intended to provide hints about the
type. In PEP 593, `MaxLen` is an example of prescribing constraints on
value. It would apply to an attribute if that attribute was annotated
with it as a type hint.

By the way, to see real code implementing this convention see:
https://github.com/fondat/fondat-core/blob/main/fondat/validation.py#L41

Here's another place that defines annotations that can be used to
enhance API documentation (e.g. OpenAPI):
https://github.com/fondat/fondat-core/blob/main/fondat/annotation.py

(Disclosure: this is code I wrote.)

Being able to define a new type like this using Annotated has proven to
be very powerful. You can apply constraints and 

> It's the *class* that is annotated. But note that the mapping is
> between 
> the attribute name to annotation, so in the sense that attributes are
> represented by their name, it is the attribute that is annotated.

It's unfortunate that the name `Annotated` was selected, because it's
definitely a point that can result in confusion. An attribute can have
an annotation (i.e. has a type hint); however, is `Annotated`
annotating the attribute? It's an object that contains multiple values,
which can be applied to an attribute as an annotation (type hint).

> Unlike modules, classes and functions, the annotation cannot be on
> the 
> attribute's *value*, because the attribute may not even have a value
> at 
> this point. And even if it does, it might be immutable, or like the 
> type, many different attributes, with different annotations, may be 
> sharing the same value.

Agree.

> This rules out putting the docstring on the attribute directly.

Agree.

> The syntax shows us annotating the attribute, and that's exactly what
> got annotated.

I'm still not in aligned on this point. I think I agree that if you
annotate an attribute with `Annotated`, you're defining a pseudo type
that can serve to document the attribute. However, as I've
demonstrated, that can be inherited by defining that type in advance
and using it to annotate multiple attributes. As I suggested, I think a
reasonable approach could be to either take the last string in the
annotation, or combine multiple strings if present.

_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/YAWO5EUWMC2HLY6XF55GW2NBOW3XTJ4B/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to