Класс _BaseThing никогда не следует явно создавать в программе , поэтому у него есть префикс _.
У меня также есть фабричный класс Thing, который создает определенный класс (
Код: Выделить всё
CubeThing
Важно, чтобы в дополнение к общим параметрам каждая Вещь реализация имеет свои дополнительные уникальные параметры (у куба есть длина ребра, у сферы — радиус и 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)
Однако мне бы хотелось увидеть это, как только я введу первый аргумент (
Код: Выделить всё
thing_type
То есть в случае с приведенным выше примером я хочу, чтобы он писал не то, что я пропустил недопустимый тип, но я передал недостаточно аргументов.
Я подумал, что, возможно, проблема в том, что я перегружаю метод __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