У меня есть следующие классы:
from abc import ABC, abstractmethod
class VarCharType(str, ABC):
def __init__(self, value):
self._validate_length(value)
def _validate_length(self, value: str):
if not self._min_length <= len(value) <= self._max_length:
raise TypeError(f'Length must be between {self._min_length} and {self._max_length}')
@property
@abstractmethod
def _min_length(self) -> int:
pass
@property
@abstractmethod
def _max_length(self) -> int:
pass
class GivenName(VarCharType):
_MIN_LENGTH = 1
_MAX_LENGTH = 255
@property
def _min_length(self) -> int:
return self._MIN_LENGTH
@property
def _max_length(self) -> int:
return self._MAX_LENGTH
class FamilyName(VarCharType):
...
Чтобы протестировать свой код, я решил создать случайные значения FamilyName
и GivenName
с помощью шаблона Mother. Что-то вроде того:
class GivenNameMother:
def random_max(self) -> GivenName:
return GivenName(''.join(random.choices(string.ascii_uppercase, k=255)))
def random_min(self) -> GivenName:
return GivenName(''.join(random.choices(string.ascii_uppercase, k=1)))
class FamilyNameMother:
def random_max(self) -> FamilyName:
return FamilyName(''.join(random.choices(string.ascii_uppercase, k=255)))
def random_min(self) -> FamilyName:
return FamilyName(''.join(random.choices(string.ascii_uppercase, k=1)))
Предыдущая реализация имела несколько проблем:
Я попробовал несколько решений, но они очень грязные, и мне это не нравится.
Каким было бы лучшее решение? Это требование, позволяющее избегать ввода Any из пакета ввода.
Спасибо!
Прежде всего позвольте мне сказать, что это не идеальное решение. Вам все равно нужно будет выяснить, как именно вы хотите делиться информацией между классами, но это должно, по крайней мере, показать вам, как вы можете иметь общий NameMother
, который по-прежнему будет поддерживать хорошую типизацию.
Итак, несколько замечаний:
_MIN_LENGTH
и _MAX_LENGTH
. Это связано с тем, что _min_length
и _max_length
настроены как методы экземпляра, а не как статические методы, поэтому они недоступны без экземпляра класса. Если мы создадим экземпляр, нам придется передать значение, и, не зная минимального или максимального значения, мы потенциально можем столкнуться с ошибкой ValueError.import random
import string
from abc import ABC, abstractmethod
from typing import Generic, TypeVar
class VarCharType(str, ABC):
_MIN_LENGTH: int
_MAX_LENGTH: int
def __init__(self, value: str) -> None:
self._validate_length(value)
def _validate_length(self, value: str) -> None:
if not self._min_length <= len(value) <= self._max_length:
raise TypeError(f'Length must be between {self._min_length} and {self._max_length}')
@property
@abstractmethod
def _min_length(self) -> int:
pass
@property
@abstractmethod
def _max_length(self) -> int:
pass
_T = TypeVar('_T', bound=VarCharType)
class NameMother(Generic[_T]):
klass: type[_T]
def __init__(self, klass: type[_T]) -> None:
self.klass = klass
def random_max(self) -> _T:
return self.klass(''.join(random.choices(string.ascii_uppercase, k=self.klass._MAX_LENGTH)))
def random_min(self) -> _T:
return self.klass(''.join(random.choices(string.ascii_uppercase, k=self.klass._MIN_LENGTH)))
class GivenName(VarCharType):
_MIN_LENGTH = 1
_MAX_LENGTH = 255
@property
def _min_length(self) -> int:
return self._MIN_LENGTH
@property
def _max_length(self) -> int:
return self._MAX_LENGTH
given_name_mother = NameMother(GivenName)
print(given_name_mother.random_max())
print(given_name_mother.random_min())
Выход:
IESFIVCVYRPDBGQWQWWVVRHXQUSUJVDCUSFPEAFOPGENUWLQRSYDFJCUEVMFJXQVNJXFWQJWOLYVPBFROLHXZCIMYDYUGXBJNIYLZTVLWUBNWRLHDOGHJFHIQJSBHZPMPBSKXOJLGNLAKQVWGHKUTGQIEXCMCAKBGSBCZTCKHKGQXPLITMKHWHBQRAJBDYOVBGETGGUXVPNXLQGOGZGAPWTZZFEUXRFSNRCATRFGQBVYMDNNPZSXJOEZMSEYHDR
J