I think you're right that the redefinition style is easier to read for complicated stuff... It also seems more complicated in a way I can't put my finger on.
The overload precedent helps. Currently leaning towards Jukka being right, vague worries about extra complication be damned. Readability is more important. > On May 10, 2017, at 5:23 AM, Jukka Lehtosalo <jlehtos...@gmail.com> wrote: > > Even if Callable types will soon support keyword arguments, the syntax for > Callables will look quite different from function definitions and this > inconsistency may hurt readability, at least for more complex signatures. We > could work around this by using the def syntax for the declared type of a > decorator. For example: > > @declared_type > def session(url: str) -> ContextManager[DatabaseSession]: ... # Explicit > '...' > > @contextmanager > def session(url: str) -> Iterator[DatabaseSession]: > s = DatabaseSession(url) > ... > > This would be quite similar to how overloads work, so there is a precedent > for something like this. We could require or recommend that the declared type > comes immediately before the implementation so that the entire definition of > a single function would not be too spread out. > > This won't help if the decorated type is not a callable. We could support > this use case by using the normal variable annotation syntax: > > thing: Decorated # Declared type of 'thing' > > @decorator > def thing() -> int: > ... > > Jukka > >> On Wed, May 10, 2017 at 12:27 AM, Naomi Seyfer <na...@seyfer.org> wrote: >> Stay tuned for the pep that allows callable to take keyword args. >> >>> On May 9, 2017, at 3:59 PM, Brett Cannon <br...@python.org> wrote: >>> >>> The idea seems reasonable to me when viewing type hints as a form of >>> documentation as it helps remind people how they are expected to call the >>> final function. >>> >>> One worry I do have, though, is Callable doesn't support keyword-only >>> parameters, so declared_type won't work in all cases without Callable >>> gaining such support (for those that don't know, Callable didn't start with >>> that support as Callable has been meant for callback scenarios up to this >>> point). >>> >>>> On Tue, 9 May 2017 at 10:21 Guido van Rossum <gu...@python.org> wrote: >>>> There's a PR to the peps proposal here: >>>> https://github.com/python/peps/pull/242 >>>> >>>> The full text of the current proposal is below. The motivation for this is >>>> that for complex decorators, even if the type checker can figure out >>>> what's going on (by taking the signature of the decorator into account), >>>> it's sometimes helpful to the human reader of the code to be reminded of >>>> the type after applying the decorators (or a stack thereof). Much >>>> discussion can be found in the PR. Note that we ended up having `Callable` >>>> in the type because there's no rule that says a decorator returns a >>>> function type (e.g. `property` doesn't). >>>> >>>> This is a small thing but I'd like to run it by a larger audience than the >>>> core mypy devs who have commented so far. There was a brief discussion on >>>> python-ideas (my original, favorable reply by Nick, my response). >>>> >>>> Credit for the proposal goes to Naomi Seyfer, with discussion by Ivan >>>> Levkivskyi and Jukka Lehtosalo. >>>> >>>> If there's no further debate here I'll merge it into the PEP and an >>>> implementation will hopefully appear in the next version of the typing >>>> module (also hopefully to be included in CPython 3.6.2 and 3.5.4). >>>> >>>> Here's the proposed text (wordsmithing suggestions in the PR please): >>>> >>>> +Decorators >>>> +---------- >>>> + >>>> +Decorators can modify the types of the functions or classes they >>>> +decorate. Use the ``decorated_type`` decorator to declare the type of >>>> +the resulting item after all other decorators have been applied:: >>>> + >>>> + from typing import ContextManager, Iterator, decorated_type >>>> + from contextlib import contextmanager >>>> + >>>> + class DatabaseSession: ... >>>> + >>>> + @decorated_type(Callable[[str], ContextManager[DatabaseSession]]) >>>> + @contextmanager >>>> + def session(url: str) -> Iterator[DatabaseSession]: >>>> + s = DatabaseSession(url) >>>> + try: >>>> + yield s >>>> + finally: >>>> + s.close() >>>> + >>>> +The argument of ``decorated_type`` is a type annotation on the name >>>> +being declared (``session``, in the example above). If you have >>>> +multiple decorators, ``decorated_type`` must be topmost. The >>>> +``decorated_type`` decorator is invalid on a function declaration that >>>> +is also decorated with ``overload``, but you can annotate the >>>> +implementation of the overload series with ``decorated_type``. >>>> + >>>> >>>> -- >>>> --Guido van Rossum (python.org/~guido) >>>> _______________________________________________ >>>> 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/brett%40python.org >> >> _______________________________________________ >> 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/jlehtosalo%40gmail.com >> >
_______________________________________________ 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