2 votes

Type hint for Callable that takes kwargs

Je veux faire quelque chose comme

from typing import Callable

def a(foo: Callable[[int], None]):
    foo(b=5)

Ce code fonctionne, mais affiche un avertissement Argument inattendu.

En définissant comme

def a(foo: Callable[[int], None]):
    foo(5)

fonctionne sans avertissement comme prévu.


Comment puis-je passer un argument attendu en tant que kwarg dans une fonction sans que le type checker soit en colère contre moi?

1voto

DeepSpace Points 31729

Les Callable docs disent

Il n'y a pas de syntaxe pour indiquer des arguments facultatifs ou des mots-clés ; de tels types de fonctions sont rarement utilisés en tant que types de rappel.

Cependant, ils disent aussi

Callable[..., ReturnType] (points de suspension littéraux) peut être utilisé pour suggérer le type d'un appel prenant un nombre quelconque d'arguments et renvoyant ReturnType

En appliquant ici, cela serait

def a(foo: Callable[..., None]):

Vous perdrez l'annotation int, mais c'est soit cela, vivre avec l'avertissement ou le surpasser explicitement.

1voto

juanpa.arrivillaga Points 35811

Vous pouvez utiliser un "protocole appelable" ici, donc:

import typing

class MyCallableType(typing.Protocol):
    def __call__(self, bar:int) -> None:
        ...

def a(foo: MyCallableType):
    foo(32)
    foo(bar=32)

Maintenant, testons ce qui précède avec mypy:

jarrivillaga$ mypy --version
mypy 0.910
jarrivillaga$ mypy test.py
Success: no issues found in 1 source file

Notez que cela permet à mypy de détecter toutes sortes d'erreurs, par exemple une fonction avec un nom d'argument incorrect, ou si nous voulons que b soit une fonction qui spécifie un argument bar avec mot-clé uniquement:

import typing

class MyCallableType(typing.Protocol):
    def __call__(self, b:int) -> None:
        ...

def a(foo: MyCallableType):
    foo(32)
    foo(b=32)

def bar(b: int) -> None:
    pass

def baz(*, b: int) -> None:
    pass

def bing(x: int) -> None:
    pass

a(bar)
a(baz)
a(bing)

Et mypy se plaindra avec ce qui suit:

jarrivillaga$ mypy test.py
test.py:21: error: Argument 1 to "a" has incompatible type "Callable[[NamedArg(int, 'b')], None]"; expected "MyCallableType"
test.py:22: error: Argument 1 to "a" has incompatible type "Callable[[int], None]"; expected "MyCallableType"
Found 2 errors in 1 file (checked 1 source file)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X