Различение однородных и гетерогенных кортежей в перегрузках функций PythonPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Различение однородных и гетерогенных кортежей в перегрузках функций Python

Сообщение Anonymous »

Предположим, у меня есть база интерфейса с множеством реализаций

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

from abc import ABC

class Base(ABC): ...

class A(Base): ...
class B(Base): ...
class C(Base): ...
# ...
class Z(Base): ...
Теперь я хочу определить составной класс, содержащий замороженный набор таких объектов. Существует общий интерфейс Product и две реализации, которые используют либо гетерогенный замороженный набор (

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

MixedProduct
) или однородный замороженный набор Z (

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

ZProduct
)

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

from abc import ABC, abstractmethod
from dataclasses import dataclass

class Product(ABC):
@property
@abstractmethod
def items(self) -> frozenset[Base]: ...

@dataclass(frozen=True)
class MixedProduct(Product):
items: frozenset[Base]

@dataclass(frozen=True)
class ZProduct(Product):
items: frozenset[Z]
есть фабричная функция, которая принимает произвольное количество объектов Base и возвращает правильный объект Product

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

from collections.abc import Iterable
from typing_extensions import TypeGuard

def check_all_z(items: tuple[Base, ...]) -> TypeGuard[tuple[Z, ...]]:
return all([isinstance(item, Z) for item in items])

def make_product(*items: Base) -> MixedProduct | ZProduct:
# `items` is a tuple[Base, ...]
if check_all_z(items):  # the TypeGuard tells MyPy that items: tuple[Z, ...] in this clause
return ZProduct(frozenset(items))
return MixedProduct(frozenset(items))
поэтому эта функция возвращает ZProduct, только если все входные элементы являются Z и MixedProduct в противном случае. Теперь я хотел бы сузить тип возвращаемого значения make_product, поскольку объединение не фиксирует возможные отношения типа ввода-возврата. Мне нужно что-то вроде этого

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

reveal_type(make_product(Z()))  # note: Revealed type is "ZProduct"
reveal_type(make_product(A()))  # note: Revealed type is "MixedProduct"
reveal_type(make_product(Z(), Z()))  # note: Revealed type is "ZProduct"
reveal_type(make_product(B(), A()))  # note: Revealed type is "MixedProduct"
reveal_type(make_product(B(), Z()))  # note: Revealed type is "MixedProduct" # also contains one Z!!
Я определяю две перегрузки

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

from typing import overload

@overload
def make_product(*items: Base) -> MixedProduct: ...

@overload
def make_product(*items: Z) -> ZProduct: ...

def make_product(*items):
if check_all_z(
items
):  # the TypeGuard tells MyPy that items: tuple[Z, ...] in this clause
return ZProduct(frozenset(items))
return MixedProduct(frozenset(items))
поэтому первая перегрузка — это «объединить все», а вторая — это специализация для единственного случая, когда вы можете получить ZProduct. Но теперь MyPy жалуется на

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

error: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader  [misc]
Итак, мой вопрос: есть ли способ просто специализировать аннотации для make_product для этого конкретного случая, который бы возвращал ZProduct каким-либо другим способом? С перегрузкой это возможно только в том случае, если все задействованные типы вообще не перекрываются. Это означало бы, что мне придется определить объединение всех других реализаций Base кроме Z и использовать его в качестве входных данных для варианта MixedProduct. Но это также не работает, потому что вы можете использовать Z во входных элементах для варианта MixedProduct, но не во всех из них (см. последний пример show_type выше). FWIW, использующий объединение всех реализаций Base (включая Z) для варианта MixedProduct, вызывает ту же ошибку MyPy.
Как еще бы я мог уметь различать однородные и гетерогенные кортежи с помощью аннотаций типов, чтобы зафиксировать правильные отношения типа ввода-возврата в моем случае?
Чтобы внести ясность: фактический код времени выполнения делает то, что я намереваюсь, я просто не могу правильно подобрать аннотации типов.

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

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

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

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

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

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Замена однородных текстур (OGL)
    Anonymous » » в форуме C++
    0 Ответы
    19 Просмотры
    Последнее сообщение Anonymous
  • Почему компилятор останавливает поиск имени на перегрузках?
    Anonymous » » в форуме C++
    0 Ответы
    10 Просмотры
    Последнее сообщение Anonymous
  • Создание потока нескольких кортежей из одной пары кортежей
    Anonymous » » в форуме JAVA
    0 Ответы
    28 Просмотры
    Последнее сообщение Anonymous
  • Различение чистого сигнала и шумового сигнала в Python
    Anonymous » » в форуме Python
    0 Ответы
    56 Просмотры
    Последнее сообщение Anonymous
  • Typehint *args для гетерогенных возвращаемых значений переменной длины, таких как asyncio.gather()
    Anonymous » » в форуме Python
    0 Ответы
    21 Просмотры
    Последнее сообщение Anonymous

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