Как указать тип, который является суммой других типов?Python

Программы на Python
Anonymous
Как указать тип, который является суммой других типов?

Сообщение Anonymous »

Представим, что у нас есть 2 протокола: HasSize и HasLength. По причинам предметной области эти могут означать разные вещи, но в некоторых случаях вы хотите адаптировать одно к другому:
Для примера давайте забудем о len( ).

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

class HasSize(Protocol):
def size(self) -> int: pass

class HasLength(Protocol):
def length(self) -> int: pass
Как уже упоминалось, в распространенном (но не единственном) случае оба слова означают одно и то же. Поскольку не каждый HasSize является HasLength, а не наоборот, я не хочу, чтобы один расширял другой.
Я мог бы предоставить классы примесей:

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

class LengthAsSize:
def length(self) -> int:
return self.size()
#and vice versa
Но система типизации будет жаловаться на отсутствие метода self.size().
Я мог бы заставить их расширить оба протокола:< /p>

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

class LengthAsSize(HasLength, HasSize):
def length(self) -> int:
return self.size()
#and vice versa
но это исключит возможность

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

Protocol
метаклассы, поэтому я не смогу:

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

class Impl(NamedTuple, LengthAsSize): # will complain about metaclasses
x: list

def size(self) -> int:
return len(self.x)
Итак, я хотел бы предоставить декоратор типа, который обеспечит другой реализацию:

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

def length_as_size[T: HasLength](t: type[T]) -> T and HasSize: #THIS IS THE ISSUE
def size(self) -> int:
return self.length()
t.size = size
return t

#this won't raise any issues, but static checked won't recognize this as HasLength; it will still recognize it as HasSize, though
@length_as_size
class Impl(NamedTuple):
x: list

def size(self) -> int:
return len(self.x)
Теперь та часть, которую я прокомментировал, проблематична: X и Y не преобразуются в тип, расширяющий как X, так и Y но вместо этого считается Any. Использование & тоже не работает. Я не нашел ничего связанного с этим в документации (хотя они длинные, и возможно, я просто пропустил это).
Как мне сформулировать тип, который расширяет оба других типа таким образом?
Это не тип объединения - объединение - это "один или другой" ; мне нужно "один и другой".

Подробнее здесь: https://stackoverflow.com/questions/790 ... ther-types

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