Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typing, custom collection type

The typing module provides some handy features to enable better readability and more confidence in the correctness of the code typed.

One of the best features is that you can write something like below to describe an input dictionary with specified element-types.

def myFun(inputDict:Dict[str, int]): pass

Now I wonder, can this be "extended" to custom types? Can custom types (which act like containers) be provided indices in a formal way to tell a potential type checker the contents must be of a specific type?

For example the collections.Counter class? - Above constraint won't work when I really want a counter, since dictionaries do not provide addition operator, where counters do.

I could do something like:

def myFun(inputDict:collections.Counter): pass

But then I lose information on what the counter stores. - Is using a TypeVar the right approach here?

CounterTy = typing.TypeVar("CounterTy", collections.Counter)
def myFun(inputDict:CounterTy[str]): pass

I'm not clear if Typevar is supposed to work that way or not. EDIT: just to be clear, above code doesn't work and errors on the TypeVar line.

like image 259
paul23 Avatar asked Mar 22 '17 17:03

paul23


1 Answers

If you're writing your own container type and want to parameterize it the same way typing.Dict and other types are, you should use typing.Generic as one of your bases (with a TypeVar as its parameter):

from typing import TypeVar, Generic, Iterable

T = TypeVar('T')

class MyContainer(Generic[T]):
    def __init__(self, iterable:Iterable[T]):
        ...

    def foo(self) -> T:
        ...

def some_function(arg: MyContainer[str]) -> str:
    return arg.foo()
like image 100
Blckknght Avatar answered Sep 29 '22 02:09

Blckknght