On Sun, Dec 12, 2021 at 07:43:16PM -0800, Brendan Barnwell wrote:

>       The question is what does this annotate:
> 
> Annotated[int, "some text here"]

Nothing. There's no annotation there.

That's an expression which returns a type alias. It is just an object. 
You can print it, put it in a list, pass it to a function, use it as a 
dict key, or garbage collect it. Or even use it to annotate a variable, 
but isolated as show, it isn't annotating anything.

An annotation is "A label associated with a variable, a class attribute 
or a function parameter or return value" and that expression above is 
not a label associated with anything.

https://docs.python.org/3/glossary.html#term-annotation

To be an annotation, it must be part of a parameter annotation, or 
variable assignment annotation:

    def func(param:expression) -> expression:
        variable: expression

All three of those expressions could legitimately be called an 
annotation, even if they're not types.

Here's an analogy: you know how dicts work, right? (Of course you do.) 
We agree that in the dict

    {"Hello world": 42}

the string "Hello world" is the key associated with value 42. So in the 
context of that dict, "Hello world" is a key.

    # helloworld.py
    print("Hello world")

Is that string "Hello world" a key in a dict now? What's its value?

How about in isolation, "Hello world", with no implied context and most 
especially no dicts anywhere in sight. Is it still a key if there is no 
dict for it to be a key of?

I'm not asking whether it *could* be a key, if there was a dict. 
Obviously the answer is yes. I'm asking, what dict is "Hello world" the 
key of in the helloworld.py program above.

If we can understand that being a key describes the *role* of a string, 
in a specific context, and is not a property of the string itself, we 
should be able to understand that being an annotation is likewise 
descibing the *role* of an object, in a specific context, and is not a 
property of the object itself.

    types: "Hello world" = (int, float, Annotated[int, "..."], str)

Here, "Hello world" is an annotation, and the Annotated type alias is a 
element of a tuple. Earlier the same string was the output of a program, 
and before that it was a key. But it's the same string.

    Annotated[int, "some text here"]

can likewise be an annotation, or the output of a program, or a key in a 
dict, or an element of a tuple, depending on context. With no context, 
it is just a type object.

If its not part of an annotation statement or a function annotation, 
it's not an annotation.

https://docs.python.org/3/glossary.html#term-function-annotation

https://docs.python.org/3/reference/simple_stmts.html#annassign


> In other words what does the use of Annotated in itself annotate.  

In itself, nothing.

There's no annotation syntax in that expression. It's not a function 
annotation or a variable annotation. It doesn't create an 
`__annotations__` dunder. It meets none of the definitions of 
"annotation".


>       As Paul pointed out in his earlier message, you can create this 
> Annotated 
> thing without attaching it to any attribute.  It seems that Annotated 
> itself is annotated the type. In fact, there can be no debate about 
> what Annotated annotates, since the documentation even says it 
> explicitly (https://docs.python.org/3/library/typing.html#typing.Annotated):
> 
> > Specifically, a type T can be annotated with metadata x via the 
> typehint Annotated[T, x].

You are right about the first part of your sentence: there can be no 
debate about this. The doc is simply wrong, and it has confused you and 
others into thinking that Annotated[T, ...] has annotated T.

But if anyone wants to debate it, if you think the documentation is 
correct, then it is easy to prove me wrong, and I will happily admit 
that I have learned something new.

All you need to do is show me the annotation syntax `target: expression` 
in either of the following:

    # A bare expression, with no context.
    Annotated[int, "some text"]

    # A type alias.
    MyAlias = Annotated[int, "some text"]

Easy peasy. Point to the annotation syntax colon to prove that I am 
wrong, and the docs are right.

Or you can show me the `__annotated__` mapping with int as the key that 
either of those two lines create.

But if you can't do any of those things, then:

- there is no annotation syntax;

- there is no "label associated with a variable, a class attribute or a 
  function parameter or return value";

- there is no `__annotations__` dunder to hold that association;

and therefore **there is no annotation**. It's just an expression 
returning a type.


> The text specified in `Annotated[T, text]` is creating a sort of 
> augmented type

The docs and the implementation call them Type Aliases. "Augmented" is 
an excellent description, thank you for suggesting it.

So we can agree that Annotated[T, *metadata] returns a type alias, based 
on T, but augmented with the metadata. That is an excellent way to 
describe it, that avoids the confusion with annotations.

Yes, the primary use-case of such a type alias is to use it in 
annotations, but its just an object, you can use it for many things.


> which is like 
> "a type that is type T but additionally means such-and-such".  It is 
> true that that can type can itself later be used to annotate an 
> attribute (or variable), but at that point it will be marking the 
> variable as being of a type that incorporates the annotating text, not 
> annotating the variable itself with that text.

What you call "marking the variable" is what Python calls an annotation.

And the meaning of annotations is **not specified by the language**. 
Typing is the primary use-case but it is not the only one. Any 
alternative use of annotations has to work with a widespread assumption 
that annotations will be types, but that is doable.


>       As such, I don't think Annotated is really a good choice for this.  
>       We really want the text of the annotation to be associated with the 
> attribute itself, not with the attribute's type.  Moreover, using 
> Annotated requires the user to specify a type,

Which you can do with Any. That is hardly a major imposition for code 
that is already using typing, and for code that isn't using typing, you 
don't have to worry about it. Just use a string.


> but people should be able 
> to specify annotations for documentation even if they're not using 
> typing at all and not specifying any types.  (They shouldn't have to 
> resort to an awkward workaround like always throwing in a dummy Any type.)

And they can do that to, just by *not using a type checker*.

    @no_type_checking
    class C:
        attr: "Doc string"

Done. The doc string is recorded in the __annotations__ dunder, but you 
can post process it any way you like.

If you want a *standard* mechanism that will be blessed by the language, 
then it has to interoperate with typing.

We've already had the idea of following the variable with a bare string 
rejected:

https://www.python.org/dev/peps/pep-0224/

and I see no reason to think that the situation has changed in any way 
since then. But if you want to propose re-opening PEP 224 and having 
another go at it, be my guest.


>       As an aside, seeing what the docs say about Annotated makes me think 
> that "Annotated" is a very bad name for this thing.  It confuses the 
> idea of a type annotation (i.e., attached to a variable) with this 
> type-incorporating-a-label, where neither the label nor the type is 
> actually an annotation in the type-annotation sense (because they have 
> not been attached to a variable to annotate it).

Right!


> It seems it would have 
> been better to called Annotated "Tagged" or "Labeled" or some such thing 
> to make it clear that when you using it you are defining a new 
> special-purpose type for use in later annotations./

Indeed.


-- 
Steve
_______________________________________________
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/EDAYOO4HEJUNL7J2L4ZFWQXQDGFJKT7T/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to