How can I ensure type hints still work for my class that inherits UserList from collections?

Question:

I have a class that adds something on top of standard list behavior. To avoid re-implementing everything, I used UserList:

from collections import UserList
            
class MyList(UserList):
    ...stuff...

But now, when I do something like:

my_list = MyList([1,2,3,4])

My IDE just marks this as a MyList type and hints for things like loops don’t work:

for an_int in my_list:
    # here, IDE does not know an_int is an int

I can force override this, but at the cost of losing hinting for my custom methods by using the type comment:

my_list = MyList([1,2,3,4]) # type: list[int]

Is there something I can hint in the class definition that will tell python static analysis that the inner type is inherited from the list passed in ctor?

Asked By: Tomáลก Zato

||

Answers:

Specify a TypeVar parameter indicating the type that MyList is generic over:

from collections import UserList
from typing import TypeVar

_T = TypeVar('_T')
            
class MyList(UserList[_T]):
    pass

my_list = MyList([1,2,3,4])
reveal_type(my_list)     # Revealed type is "MyList[builtins.int]"
reveal_type(my_list[0])  # Revealed type is "builtins.int"

If you add methods that involve the items contained in the list, _T is used within the class definition to refer to the type of those items.

If _T is specified with a bound, you can limit the acceptable types for a MyList to contain; otherwise _T can be associated with any particular type at the time that you declare a given MyList instance.

Answered By: Samwise
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.