Pyright отдает приоритет количеству переданных аргументов над их типом при использовании @overloadPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Pyright отдает приоритет количеству переданных аргументов над их типом при использовании @overload

Сообщение Anonymous »

У меня есть базовый класс _BaseThing, а также его подклассы CubeThing и BallThing.
Класс _BaseThing никогда не следует явно создавать в программе , поэтому у него есть префикс _.
У меня также есть фабричный класс Thing, который создает определенный класс (

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

CubeThing
или BallThing) в зависимости от переданного типа вещи.
Важно, чтобы в дополнение к общим параметрам каждая Вещь реализация имеет свои дополнительные уникальные параметры (у куба есть длина ребра, у сферы — радиус и some_other_unique_param).

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

from __future__ import annotations
from typing import overload, Literal
from enum import Enum

class ThingType(Enum):
CUBE = 0
BALL = 1

class _BaseThing:
"""
Base class for all Things.
It shouldn't be used in real program, so it prefixed with _.
"""
def __init__(self, thing_type: ThingType, color, material):
self.type = thing_type
self.color = color
self.material = material

def change_color(self, color): ...

def change_material(self, material): ...

class CubeThing(_BaseThing):
"""
Cubical implementation of the Thing.
"""
def __init__(self, color, material, edge_length: float):
super().__init__(ThingType.CUBE, color, material)
self.edge_length = edge_length

def some_cube_method(self):
print('This is cube!')

class BallThing(_BaseThing):
"""
Spherical implementation of the Thing.
"""
def __init__(self, color, material, radius: float, some_other_unique_param: int):
super().__init__(ThingType.BALL, color, material)
self.radius = radius
self.some_other_unique_param = some_other_unique_param

def some_ball_method(self):
print('This is ball!')

class Thing:
"""Class, that looks like base class for all Things (bc of the name), but it is actually a 'fabric'."""
__thing_types_dict__ = {
ThingType.CUBE: CubeThing,
ThingType.BALL: BallThing,
}
@overload
def __new__(cls, thing_type: Literal[ThingType.CUBE], color, material, edge_length: float) -> CubeThing:
...

@overload
def __new__(cls, thing_type: Literal[ThingType.BALL], color, material,
radius: float, some_other_unique_param: int) -> BallThing:
...

def __new__(cls, thing_type: ThingType, color, material, *args, **kwargs):
if thing_type not in cls.__thing_types_dict__:
raise TypeError('Unexpected thing_type.')

return cls.__thing_types_dict__[thing_type](color, material, *args, **kwargs)
Когда я пытаюсь вызвать ball = Thing(ThingType.BALL, 'blue', 'silicon', 1), статический анализатор PyCharm (а также pyright) сообщает мне, что я передал неверный аргументthing_type (важно, что в этом примере я забыл написать последний аргумент). То есть pyright уже «выбрал» @overload с помощью CubeThing. Однако как только я добавляю последний аргумент, он сразу «переключается» на @overload с BallThing и предупреждение пропадает. Таким образом, PyCharm/pyright отдает приоритет не переданным мной типам, а количеству переданных аргументов.
Изображение

Однако мне бы хотелось увидеть это, как только я введу первый аргумент (

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

thing_type
), статический анализатор сразу определяет правильный @overload и дальше пишет на его основе предупреждения.
То есть в случае с приведенным выше примером я хочу, чтобы он писал не то, что я пропустил недопустимый тип, но я передал недостаточно аргументов.
Я подумал, что, возможно, проблема в том, что я перегружаю метод __new__, поэтому попытался написать функциональную реализацию:

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

@overload
def create_thing(thing_type: Literal[ThingType.CUBE], color, material, edge_length: float) -> CubeThing:
...

@overload
def create_thing(thing_type: Literal[ThingType.BALL], color, material,
radius: float, some_other_unique_param: int) -> BallThing:
...

def create_thing(thing_type: ThingType, color, material, *args, **kwargs):
thing_types_dict = {
ThingType.CUBE: CubeThing,
ThingType.BALL: BallThing,
}

if thing_type not in thing_types_dict:
raise TypeError('Unexpected thing_type.')

return thing_types_dict[thing_type](color, material, *args, **kwargs)
Однако этот вариант имеет точно такую ​​же проблему.
Изображение

Я также пробовал использовать строки '0' и '1' в аргументах Literal и подсказках типов вместо ThingType< /code>, но это также не помогло.

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

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

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

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

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

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

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