Quantcast
Channel: Active questions tagged python - Stack Overflow
Viewing all articles
Browse latest Browse all 17274

Typing a function decorator with conditional output type, in Python

$
0
0

I have a set of functions which all accept a value named parameter, plus arbitrary other named parameters.

I have a decorator: lazy. Normally the decorated functions return as normal, but return a partial function if value is None.

How do I type-hint the decorator, whose output depends on the value input?

from functools import partialdef lazy(func):    def wrapper(value=None, **kwargs):        if value is not None:            return func(value=value, **kwargs)        else:            return partial(func, **kwargs)    return wrapper@lazydef test_multiply(*, value: float, multiplier: float) -> float:    return value * multiplier@lazydef test_format(*, value: float, fmt: str) -> str:    return fmt % valueprint('test_multiply 5*2:', test_multiply(value=5, multiplier=2))print('test_format 7.777 as .2f:', test_format(value=7.777, fmt='%.2f'))func_mult_11 = test_multiply(multiplier=11)  # returns a partial functionprint('Type of func_mult_11:', type(func_mult_11))print('func_mult_11 5*11:', func_mult_11(value=5))

I'm using mypy and I've managed to get most of the way using mypy extensions, but haven't got the value typing working in wrapper:

from typing import Callable, TypeVar, ParamSpec, Any, Optionalfrom mypy_extensions import DefaultNamedArg, KwArgR = TypeVar("R")P = ParamSpec("P")def lazy(func: Callable[P, R]) -> Callable[[DefaultNamedArg(float, 'value'), KwArg(Any)], Any]:    def wrapper(value = None, **kwargs: P.kwargs) -> R | partial[R]:        if value is not None:            return func(value=value, **kwargs)        else:            return partial(func, **kwargs)    return wrapper

How can I type value? And better still, can I do this without mypy extensions?


Viewing all articles
Browse latest Browse all 17274

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>