> On 15 May 2017 at 10:48, Koos Zevenhoven <k7ho...@gmail.com> wrote: > >> Would __annotations__ be set by the decorator? To me, not setting them >> would seem weird, but cases where the result is not a function could >> be weird. I also don't see a mention of this only working in stubs. >> > It took me a while to realize which annotations we're talking about here.
I like Jukka's version, as it has a clear distinction between >> functions and other attributes. But that might require a language >> change to provide __annotations__ in a clean manner? Maybe that >> language change would be useful elsewhere. > > I'm not interesting in language changes to solve this problem. On Mon, May 15, 2017 at 6:20 AM, Ivan Levkivskyi <levkivs...@gmail.com> wrote: > With original syntax it is possible to overwrite annotations without > language changes. > However with Jukka's syntax it looks difficult. A possible pure-Python way > could be > to insert an item in an enclosing __annotations__, if an enclosing scope > is a class or module scope. > I assume we're talking about `session.__annotations__`, which will be overwritten by the last definition (i.e. the "implementation"). This is only a runtime problem, and we're actually still a bit better off here than for @overload -- for @overload, the implementation is often un-annotated or has very vague annotations (e.g. `*args: Any`), while here the annotations are in principle preserved by the decorators on the implementation function. (The main premise of the proposal under discussion is to clarify the type for the *human* reader, although in some edge cases the explicit annotation may provide a constraint for the naturally inferred type of the decorated function.) But in either case the annotations on the overload variants or the "declaration" are lost at runtime by the trick of using multiple definitions, since at runtime the last definition wins. (And we don't want to go through the contortions used by e.g. @property for collecting getters and setters belonging to a single attribute.) The question then is, do we care more about the runtime accessibility of the type, or do we care more about ease of use in a context of static analysis? In general with the design of PEP 484 I've tried to balance the two (and several other constraints like no changes to the core Python language). I'm still not decided. Let's compare the two proposals quickly. In Naomi's version you'd write @decorated_type(Callable[[str], ContextManager[DbSession]]) @contextmanager def session(url: str) -> Iterator[DbSession]: <body> while in Jukka's version you'd write @declared_type def session(url: str) -> ContextManager[DbSession]: ... @contextmanager def session(url: str) -> Iterator[DbSession]: <body> There's also a difference in power between the two: in Naomi's proposal, session's type becomes exactly Callable[[str], ContextManager[DbSession]] which can only be called with positional arguments, whereas in Jukka's proposal session will retain the name and clasiffication (e.g. keyword-only, varargs) of the arguments. If those are important, in Naomi's case this can be written using the new "argspecs" form of Callable, i.e. @decorated_type(Callable[[Arg(str, 'url')], ContextManager[DbSession]) @contextmanager def session <etc.> which is definitely more verbose and uglier than Jukka's version. OTOH it does mean that Naomi's proposal has all the *power* of Jukka's version -- and in simple cases it is actually less verbose than Jukka's proposal (in cases where you want all that power -- if you're happy with a basic callable it's actually *less* verbose). Jukka's version also needs another special case where the decorator returns something that's not a callable. In Naomi's proposal this would simply be @decorated_type(SomeType) @some_decorator def my_thing(url: str) -> int: <etc.> Jukka's proposal *seems* to be to just allow overriding a variable declaration with a function declararion: my_thing: SomeType @some_decorator def my_thing <etc.> This seems fragile to me (since it looks like an accidental redefinition, although typically the static check would find a discrepancy between the inferred type of the first and the second definition). All in all I'm still leaning towards Naomi's original proposal -- it looks simpler to implement as well. -- --Guido van Rossum (python.org/~guido <http://python.org/%7Eguido>)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com