Как параметризовать тип класса, созданного с помощью @classmethod в PythonPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как параметризовать тип класса, созданного с помощью @classmethod в Python

Сообщение Anonymous »

Я пытаюсь определить общий базовый класс, который может создавать экземпляры самого себя, вот так

Код: Выделить всё

from typing import Callable, TypeVar, Generic

T = TypeVar("T")
U = TypeVar("U")

class From(Generic[T]):
def __init__(self, val: T):
self.val = val

@classmethod
def unit(cls, val):
return cls(val)

def bind(self, func: Callable[[T], U]):
return self.unit(func(self.val))
В основном, при вызове привязки для экземпляра From с функцией, которая меняет тип, например

Код: Выделить всё

def to_string(i: int) -> str:
return str(i)

From(1).bind(to_string) # here, self.val = "1"
Проверка типов будет жаловаться, потому что cls в From.unit уже параметризован T (следовательно, передается U в From[ T] сообщает, что U нельзя назначить T )
Эту проблему можно решить, вернув параметризованный экземпляр From в методе unit вот так:

Код: Выделить всё

class From(Generic[T]):
...
@classmethod
def unit(cls, val: U) -> "From[U]":
return From[U](val)
и это прекрасно работает.
Однако проблема возникает, когда я позволяю другому классу наследовать от From. Я теряю общность:

Код: Выделить всё

class Just(From[T]):
pass

Just(1).bind(to_string) # equals From("1"), instead of Just("1")
Не принимая решение о том, что вам следует определить новый метод модуля с той же формой и именем класса в каждом наследующем экземпляре, есть ли способ повторно параметризовать тип переменную cls в исходном методе unit?
Я знаю, что вы можете использовать cls.__orig_bases__ для поиска (Generic[~T])< /code>, если вы распечатаете его внутри unit.
Я подумал, может быть, вы можете сделать что-то вроде setattr(cls, "__orig_bases__", (Generic))
Но это кажется бессмысленным и на случай, если не будет обнаружено проверкой типов.
В идеале должен быть какой-то метод для self, который позволит вам для доступа к непараметризованному базовому классу, чтобы вы могли self.() .
Сейчас мое решение — добавить # type: ignore в unit, например итак:

Код: Выделить всё

@classmethod
def unit(cls, val: U) -> "From[U]":
"""Return a new instance of the same encapsulating class, wrapping `val`"""
return cls(val) # type: ignore
Но это не идеально.

Подробнее здесь: https://stackoverflow.com/questions/792 ... od-in-pyth
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»