FAQ
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)
  2. 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?


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

Search Discussions

  • Guido van Rossum at May 17, 2015 at 11:50 pm

    On Sun, May 17, 2015 at 3:07 PM, Alex Gr?nholm 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())



    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.


    --
    --Guido van Rossum (python.org/~guido)
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-dev/attachments/20150517/28d2bbdd/attachment.html>
  • Alex Grönholm at May 18, 2015 at 7:14 am

    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
    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]):
         ...
    --
    --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/81c295c1/attachment.html>
  • Guido van Rossum at May 18, 2015 at 3:05 pm
    On Mon, May 18, 2015 at 12:14 AM, Alex Gr?nholm wrote:


    18.05.2015, 02:50, Guido van Rossum kirjoitti:
    On Sun, May 17, 2015 at 3:07 PM, Alex Gr?nholm 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.)



    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)
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-dev/attachments/20150518/fea1a6dd/attachment.html>
  • Alex Grönholm at May 18, 2015 at 6:01 pm

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

    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-dev/attachments/20150518/b1556df0/attachment-0001.html>
  • Guido van Rossum at May 18, 2015 at 7:32 pm
    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 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>
  • Ivan Levkivskyi at May 18, 2015 at 11:59 am

    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())

    I think Alex means this: https://github.com/ambv/typehinting/issues/107
    This could be really useful, for example:


    def fancy_instantiate(cls: Type[T]) -> T:
         ...
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-dev/attachments/20150518/1d508d26/attachment.html>

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-dev @
categoriespython
postedMay 17, '15 at 10:07p
activeMay 18, '15 at 7:32p
posts7
users3
websitepython.org

People

Translate

site design / logo © 2017 Grokbase