Как мне инициализировать базовый `tuple` при выводе из` typing.Tuple`? - PullRequest
0 голосов
/ 13 мая 2018

Согласно документам , «встроенные универсальные типы .. допустимы как в качестве типов, так и в качестве базовых классов».Он приводит пример, полученный из Dict[str, List[Node]].

Однако, когда я пытаюсь сделать это с Tuple[int, int], конструктор не переходит должным образом.Например:

from typing import Tuple

class MyTuple(Tuple[int, int]):
    def hello(self):
        print("hello: " + str(len(self)))

MyTuple([1, 2]).hello()

печатает hello: 0.Если вместо этого я наследую от встроенного tuple, он напечатает hello: 2.

Как я могу инициализировать базовый tuple объект при выводе из Tuple[int, int]?

1 Ответ

0 голосов
/ 13 мая 2018

Типы в модуле typing на самом деле не предназначены для непосредственного создания экземпляров: они должны использоваться как статические подсказки типов в аннотациях.

Но если вам действительно нужно, вы можете переопределить __new__(), чтобы вернуть кортеж:

class MyTuple(Tuple[int, int]):

    def __new__(cls, *args, **kwargs):
        return tuple(*args, **kwargs)

print(MyTuple('abc'))  # -> ('a', 'b', 'c')

Это будет создавать простые объекты кортежа каждый раз, когда вы вызываете MyTuple(). Если вместо этого вы хотите, чтобы объекты были экземплярами вашего класса:

class MyTuple(Tuple[int, int]):

    def __new__(cls, *args, **kwargs):
        return tuple.__new__(cls, *args, **kwargs)

print(MyTuple('abc'))  # -> ('a', 'b', 'c')
print(type(MyTuple('abc')))  # -> __main__.MyTuple

Это работает, потому что typing.Tuple является подклассом tuple.

Обратите внимание, что вызов super().__new__() не будет работать, потому что typing.Tuple (и другие универсальные типы) отбрасывают передаваемые им аргументы. Вы должны «замкнуть накоротко», позвонив tuple.__new__() напрямую.

...