Allow me to chime in. Am 13.08.2014 22:19, schrieb Guido van Rossum:
On Wed, Aug 13, 2014 at 12:59 PM, Ethan Furman
mailto:ethan@stoneleaf.us> wrote: -1 on deprecating alternative uses of annotations.
Do you have a favorite alternative annotation use that you actually use (or are likely to)?
I would be very sad to see annotations being limited to convey type information. But I think I have a solution that will make all happy (see end of mail) I've programmed Java web application for many years now (hoping to finally switch to Python), and "method parameter annotations" as they are called in Java would be one thing I'd really miss, as they can be very useful. Let me give you two examples: 1. Annotations can be used to communicate additional restrictions on values that must be checked on run time Let's assume a simple Web service that is called via HTTP to register a user, and the underlying framework decodes the request and finally calls a simple controller function, it could look like this (Java code, @ signifies an annotation) public Response register(@Range(18,100) int age, @ValidEmail String email) { ... } The framework would check the range of the age parameter and the validity of the email and if there are validation errors, refusing the request with a suitable error message without ever calling our function. Even if we assume that mypy's type system will be incredibly complex and allowing to specify all kinds of restrictions on a type, it won't help because those checks have to be done at run time, and are not optional. Of course those checks could be hard coded into the function, but using annotation also provides a simple and immediate documentation about the allowed values, and avoids boilerplate (I do not have to write "if (emailNotvalie(email) throw ValidationError("Field email is not a valid email")" in every method that uses an email) 2. They can give meta information to a framework An admittedly contrieved example, let's expand our register function: public Response register( int age, @Inject @Scope("session") UserService userService, @Authenticated User user) .... Here I can tell the dependency injection framework that I want an instance of the UserService injected, but one instance that has session scope instead of the normal "singleton" scope. I also ask the framework to inject me the currently authenticated user object (let's assume if I'd write "@Authenticated String user" I could get the login name as string etc.) The flexibility annotations give in Java makes programming much less frustrating. It also took quite some time before annotations were widly used (they were only available starting in Java 5) and people started finding more uses for them. I think this will also be true for Python, it will take time before people find useful ways for them. Redefining them now to be "not much more" than static type information feels wrong to me. My proposed solution: If an annotation is a tuple, mypy will take a look at each item and do it's usual thing. If it doesn't recognise an item, it is skipped. Every framework that uses annotations should also iterate over entries of a tuple to find the ones it is interested in. This also allows more than one annotation at a time, and is completely backwards compatible (as far as Python itself is concerned) for example, my first example could be written as def register(age: (int, range(18,100)), email: (str, ValidEmail)) also, it will allow me to add annotations to existing "typed" functions, def foo(bar: int) -> int could become def foo(bar: (int, MyAnnotation)) -> (int, AnotherOfMyAnnotations) I'm not sure what should happen if two conflicting types are given, like (int, str); I think it should be treated as a union type (either int or str). -- Dennis