Список подклассов Python со всеми элементами одного типа - PullRequest
0 голосов
/ 17 марта 2020

Я ищу способ сделать подкласс list, где все элементы имеют одинаковый тип. Мне не нужна полностью обобщенная c реализация, , как описано в этом ответе .

. То, что я хотел бы, - это что-то примерно эквивалентное следующему коду (используя typing) :

class NumberParty(list[int]):
    def __str__(self) -> str:
        "?".join([str(x) for x in self])

    def total(self) -> int:
        return sum(self)

Причина, по которой я хочу использовать этот класс вместо аннотаций List[int], заключается в том, что я использую метод __str__, описанный выше, в нескольких местах и ​​хочу исключить скопированные строки кода.


В качестве дополнительного вопроса, было бы разумно перегрузить __init__ чем-то похожим на следующий код?

__init__(self, *numbers: int):
    self = numbers
__init__(self, nums: Iterable[int]):
    self = list(nums)

Первым способом было бы непосредственное создание нового NumberParty экземпляр, в то время как второй создаст его из существующего списка или набора целых чисел.

1 Ответ

1 голос
/ 18 марта 2020

Если я не понимаю ваш вопрос, просто выполните:

from typing import List

class NumberParty(List[int]):
    def __str__(self) -> str:
        return "?".join([str(x) for x in self])

    def total(self) -> int:
        return sum(self)

... должно просто сработать.

Обратите внимание, что наследование от List[int] по сути то же самое, что наследование от list - единственное различие заключается в том, что контролеры типов поймут, что должен содержать ваш пользовательский класс, и проверят, что вы используете методы типа append(...) безопасным для типов способом.

Однако нет разница во время выполнения, и вы все равно можете свободно игнорировать свою проверку типов и добавлять строки или что-то подобное, точно так же, как Python позволяет добавлять строки в обычные списки, аннотированные как тип List [int].

А так как этот класс является подтипом List [int], фрагменты кода, подобные приведенным ниже, должны проверять тип:

def expect_list(x: List[int]) -> None: pass

def expect_number_party(x: NumberParty) -> None: pass

n = NumberParty()

# Both type checks
expect_list(n)
expect_number_party(n)

По поводу вашего вопроса о переопределении __init__ - вам нужно вызвать супер конструктор, если вы решите выбрать этот маршрут, чтобы убедиться, что класс настроен правильно.

...