Поскольку вы определяете поле в классе, практический подход заключается в подсказке типа поля.Обратите внимание, что вы должны указать mypy
не проверять саму строку.
class Person(PersonBase):
age: int = IntField() # type: ignore
Это наименьшее изменение, но довольно негибкое.
Вы можете создавать автоматически набранные, общие подсказки, используя вспомогательную функцию с поддельной подписью:
from typing import Type, TypeVar
T = TypeVar('T')
class __Field__:
"""The actual field specification"""
def __init__(self, *args, **kwargs):
self.args, self.kwargs = args, kwargs
def Field(tp: Type[T], *args, **kwargs) -> T:
"""Helper to fake the correct return type"""
return __Field__(tp, *args, **kwargs) # type: ignore
class Person:
# Field takes arbitrary arguments
# You can @overload Fields to have them checked as well
age = Field(int, True, object())
Вот так библиотека attrib
предоставляет свои устаревшие подсказки.Этот стиль позволяет скрыть всю магию / хаки аннотаций.
Поскольку метакласс может проверять аннотации, нет необходимости хранить тип в поле.Вы можете использовать только Field
для метаданных и аннотацию для типа:
from typing import Any
class Field(Any): # the (Any) part is only valid in a .pyi file!
"""Field description for Any type"""
class MetaPerson(type):
"""Metaclass that creates default class attributes based on fields"""
def __new__(mcs, name, bases, namespace, **kwds):
for name, value in namespace.copy().items():
if isinstance(value, Field):
# look up type from annotation
field_type = namespace['__annotations__'][name]
namespace[name] = field_type()
return super().__new__(mcs, name, bases, namespace, **kwds)
class Person(metaclass=MetaPerson):
age: int = Field()
Так attrib
предоставляет свои атрибуты Python 3.6+.Он является общим и соответствует стилю аннотации.Обратите внимание, что это также может использоваться с обычным базовым классом вместо метакласса.
class BasePerson:
def __init__(self):
for name, value in type(self).__dict__.items():
if isinstance(value, Field):
field_type = self.__annotations__[name]
setattr(self, name, field_type())
class Person(BasePerson):
age: int = Field()