[Python-Dev] PEP 484 wishes

Alex Grönholm alex.gronholm at nextday.fi
Mon May 18 20:01:06 CEST 2015



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 <mailto: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 <mailto: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>)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20150518/b1556df0/attachment-0001.html>


More information about the Python-Dev mailing list