After the inclusion of PEP 3102 and PEP 570 it is now possible to:
Write functions that take keyword-only parameters:
def divide(*, dividend: float, divisor: float) -> float:
return dividend / divisor
Write functions that take positional-only parameters:
def summation(a: float, b: float, /) -> float:
return a + b
Write functions that take positional-only and keyword-only parameters:
def difference(a: float, b: float, /, *, absolute: bool = True) -> float:
return abs(a - b) if absolute else a - b
Type Hints work fine in all cases above, but if these functions are in a closure or part of a another data structure, Pylance throws warnings for the return types.
Example of putting functions in dictionaries:
container_divide: dict[str, Callable[[float, float], float]] = {
"divide": divide # Warning
}
container_summation: dict[str, Callable[[float, float], float]] = {
"summation": summation # No Warning
}
container_difference: dict[str, Callable[[float, float, bool], float]] = {
"difference": difference # Warning
}
The warnings are:
Expression of type "dict[str, (*, dividend: float, divisor: float) -> float]" cannot be assigned to declared type "dict[str, (float, float) -> float]"
Type "(*, dividend: float, divisor: float) -> float" cannot be assigned to type "(float, float) -> float"
Function accepts too many positional parameters; expected 0 but received 2
Keyword parameter "dividend" is missing in destination
Keyword parameter "divisor" is missing in destination
Expression of type "dict[str, (a: float, b: float, /, *, absolute: bool = True) -> float]" cannot be assigned to declared type "dict[str, (float, float, bool) -> float]"
Type "(a: float, b: float, /, *, absolute: bool = True) -> float" cannot be assigned to type "(float, float, bool) -> float"
Function accepts too many positional parameters; expected 2 but received 3
The same situation happens with closures:
def curry_divide(*, divisor: float) -> Callable[[float], float]:
def inner_divide(*, dividend: float) -> float:
return dividend / divisor
return inner_divide # Warning
def curry_summation(a: float, /) -> Callable[[float], float]:
def inner_summation(b: float, /) -> float:
return a + b
return inner_summation # No Warning
def curry_difference(a: float, /) -> Callable[[float, bool], float]:
def inner_difference(b: float, /, *, absolute: bool = True) -> float:
result = a - b
return abs(result) if absolute else result
return inner_difference # Warning
The warnings are:
Expression of type "(*, dividend: float) -> float" cannot be assigned to return type "(float) -> float"
Type "(*, dividend: float) -> float" cannot be assigned to type "(float) -> float"
Function accepts too many positional parameters; expected 0 but received 1
Keyword parameter "dividend" is missing in destination
Expression of type "(b: float, /, *, absolute: bool = True) -> float" cannot be assigned to return type "(float, bool) -> float"
Type "(b: float, /, *, absolute: bool = True) -> float" cannot be assigned to type "(float, bool) -> float"
Function accepts too many positional parameters; expected 1 but received 2
What would be the proper way to add type hints so that there are no warnings? I am only interested in built-in solutions or using the typing_extensions module. No other external libraries.