[Python-Dev] PEP 484 wishes
Guido van Rossum
guido at python.org
Mon May 18 21:32:35 CEST 2015
Can you add your example to the issue?
https://github.com/ambv/typehinting/issues/107
We're trying to finish up PEP 484 in the next few days (wait for an
announcement :-) and we just don't have time for every use case; but over
the course of 3.5 we will be adding features that are considered useful,
and we'll keep the issue open to remind us of it. Until then you'll have to
use plain "type" as the annotation (still better than "Any". :-)
On Mon, May 18, 2015 at 11:01 AM, Alex Grönholm <alex.gronholm at nextday.fi>
wrote:
>
>
> 18.05.2015, 18:05, Guido van Rossum kirjoitti:
>
> On Mon, May 18, 2015 at 12:14 AM, Alex Grönholm <alex.gronholm at nextday.fi
> > wrote:
>
>>
>>
>> 18.05.2015, 02:50, Guido van Rossum kirjoitti:
>>
>> On Sun, May 17, 2015 at 3:07 PM, Alex Grönholm <alex.gronholm at nextday.fi
>> > wrote:
>>
>>> Looking at PEP 484, I came up with two use cases that I felt were not
>>> catered for:
>>>
>>> 1. Specifying that a parameter should be a subclass of another
>>> (example: Type[dict] would match dict or OrderedDict; plain "Type" would
>>> equal "type" from builtins)
>>>
>>>
>> I don't understand. What is "Type"? Can you work this out in a full
>> example? This code is already okay:
>>
>> def foo(a: dict):
>> ...
>>
>> foo(OrderedDict())
>>
>> This code is passing an *instance* of OrderedDict. But how can I
>> specify that foo() accepts a *subclass* of dict, and not an instance
>> thereof?
>>
>> A full example:
>>
>> def foo(a: Type[dict]):
>> ...
>>
>> foo(dict) # ok
>> foo(OrderedDict) # ok
>> foo({'x': 1}) # error
>>
>
> You want the argument to be a *class*. We currently don't support that
> beyond using 'type' as the annotation. We may get to this in a future
> version; it is relatively uncommon. As to what notation to use, perhaps it
> would make more sense to use Class and Class[dict], since in the world of
> PEP 484, a class is a concrete thing that you can instantiate, while a type
> is an abstraction used to describe the possible values of a
> variable/argument/etc.
>
> Also, what you gave is still not a full example, since you don't show what
> you are going to do with that type. Not every class can be easily
> instantiated (without knowing the specific signature). So if you were
> planning to instantiate it, perhaps you should use Callable[..., dict] as
> the type instead. (The ellipsis is not yet supported by mypy --
> https://github.com/JukkaL/mypy/issues/393 -- but it is allowed by the
> PEP.)
>
> Here's one example, straight from the code of my new framework:
>
> @typechecked
> def register_extension_type(ext_type: str, extension_class: type, replace:
> bool=False):
> """
> Adds a new extension type that can be used with a dictionary based
> configuration.
>
> :param ext_type: the extension type identifier
> :param extension_class: a class that implements IExtension
> :param replace: ``True`` to replace an existing type
> """
>
> assert_subclass('extension_class', extension_class, IExtension)
> if ext_type in extension_types and not replace:
> raise ValueError('Extension type "{}" already
> exists'.format(ext_type))
>
> extension_types[ext_type] = extension_class
>
> I would like to declare the second argument as "extension_class:
> Type[IExtension]" (or Class[IExtension], doesn't matter to me). Likewise,
> the type hint for "extension_types" should be "Dict[str, Type[IExtension]]".
>
>
>
>>
>>
>>>
>>> 1. Specifying that a callable should take at least the specified
>>> arguments but would not be limited to them: Callable[[str, int, ...], Any]
>>>
>>> Case #2 works already (Callable[[str, int], Any] if the unspecified
>>> arguments are optional, but not if they're mandatory. Any thoughts?
>>>
>> For #2 we explicitly debated this and found that there aren't use cases
>> known that are strong enough to need additional flexibility in the args of
>> a callable. (How is the code calling the callable going to know what
>> arguments are safe to pass?) If there really is a need we can address in a
>> future revision.
>>
>> Consider a framework where a request handler always takes a Request
>> object as its first argument, but the rest of the arguments could be
>> anything. If you want to only allow registration of such callables, you
>> could do this:
>>
>> def calculate_sum(request: Request, *values):
>> return sum(values)
>>
>> def register_request_handler(handler: Callable[[Request, ...], Any]):
>> ...
>>
>
> Hm... Yeah, you'd be stuck with using Callable[..., Any] for now. Maybe
> in a future version of the PEP. (We can't boil the ocean of typing in one
> PEP. :-)
>
> --
> --Guido van Rossum (python.org/~guido <http://python.org/%7Eguido>)
>
>
>
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/guido%40python.org
>
>
--
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20150518/af035a48/attachment.html>
More information about the Python-Dev
mailing list