top | item 25429551

(no title)

londt8 | 5 years ago

This may seem like a good idea, but it gets problematic since you need to always use isinstance checks. Its actually discouraged to return union types by the mypy team: https://github.com/python/mypy/issues/1693

discuss

order

karlicoss|5 years ago

Yeah, but you need to test whether the result is an error or not in some way. In languages with better ADT/pattern matching support (like Haskell or Rust) you'd use case/match operator, or whatever it's called.

I've read the issue, and it seems that it's more about the lack of overloading/dependent types, e.g. their example with pow function. In c++ you'd have two overloads:

    float pow(float, float)
    int pow(int, int)
Whereas in python, even though you can achieve the equivalent behaviour in runtime, mypy (at least until recently) couldn't express this, so you had to define something like

    def pow(base: Union[int, float], power: Union[int, float]) -> Union[int, float]
Which might be annoying on call sites when you do expect the return type to be int (but there is no way for mypy to know that with such signature).

In my case I do want to return a variant type unconditionally, so this warning doesn't really apply. It's more similar to an Optional type (just instead of None I am using a more meaningful Exception): while it's not great if your code is riddled with optional return types, sometimes you don't have other choice but using it.

MapleWalnut|5 years ago

You can use typing.TypeVar for the `pow()` example. TypeVar was added via the original type hints PEP in 2014.

    from typing import TypeVar

    T = TypeVar('T', int, float)
    def pow(base: T, power: T) -> T: ...

hauntsaninja|5 years ago

Python's static type system can express what you describe using TypeVars or overloads. The issue is that `int pow(int, int)` is fundamentally incorrect. If the exponent is a negative integer, the return type would need to be float.

As evidenced by your comment, most people forget about negative exponents. The vast majority of usage is positive exponents; people expect an int back when they do `pow(2, 2)` and returning a Union or float would result in annoying false positives.