Is there a Python equivalent to Typescript `typeof`, or C++ `decltype`?
Asked Answered
B

1

10

Say we have a function, for instance reduce, that takes in a callback, for instance combiner. If I have an example callback function, exampleReducer, I would like to avoid having to write the type of the callback by hand and use instead the type of exampleReducer.

In C++, I can get the type of the exampleReducer using decltype:

#include <iostream>
#include <vector>
using namespace std;;

float exampleReducer(float x, float y) {
    return x+y;
}

auto reduce(decltype(exampleReducer) reducer, vector<float> numbers) { 
    auto result = numbers[0];
    for (auto x: numbers)
        result = reducer(result, x);
    return result;
};

int main() {
    std::cout << reduce([](float x, float y) {return x/y;}, {1,2,3,4,5});
}

In Typescript, I can use typeof:

const exampleReducer = (x: number, y: number) => x+y;

const reduce = (reducer: typeof exampleReducer, numbers: number[]) => {
    let result = numbers[0];
    numbers.forEach((n) => { result = reducer(result, n);})
    return result
}

console.log(reduce((x, y) => x/y, [1,2,3,4,5]))

I know that Python 3.11 will have a reveal_type function added to the typing module - already available in typing-extensions, but the documentation states:

When a static type checker encounters a call to this function, it emits a diagnostic with the type of the argument.

So it seems like type checkers can infer the type, but for debugging purposes only...

Is there a python equivalent that would allow using the type of exampleReducer as a type annotation?

def exampleReducer(x: float, y: float): 
    return x+y;

def reduce(reducer: ???what goes here??? exampleReducer, numbers: list[float]):
    result = numbers[0];
    for n in numbers:
        result = reducer(result, n)
    return result

print(reduce(lambda x, y: x/y, [1,2,3,4,5]))
Bothwell answered 7/10, 2022 at 11:57 Comment(3)
CallableProcathedral
You would need to specify all argument types and return type to Callable to achieve strict type safety: Callable[[float,float], float], which is what I would like to avoid.Bothwell
Very good answer!Idiophone
L
0

The only way that I know, is no real typeof functionality, but we have typing.Protocol, as a workaround.

class exampleReducer(typing.Protocol):
    def __call__(x: float, y: float): 
        return x+y;

def reduce(reducer: exampleReducer, numbers: list[float]):
    result = numbers[0];
    for n in numbers:
        result = reducer(result, n)
    return result

print(reduce(lambda x, y: x/y, [1,2,3,4,5]))

This code is accepted by PyCharms typechecker, because Protocol uses ducktyping instead of inheritance. But I have no clue if this works for other static typecheckers as well.

Lysozyme answered 2/7 at 10:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.