В базовом Python нет возможности делать то, что вы хотите, не меняя определения Test
.Минимальным изменением было бы аннотировать атрибут на уровне класса:
class Test:
x: int
def __init__(self):
# define self.x or not, but it needn't be annotated again
Это на самом деле прекрасно; по умолчанию предполагается, что аннотации в области видимости ссылаются на атрибуты экземпляр , а не класс атрибуты (назначение значения в области видимости класса создает атрибут класса, ноаннотировать это не надо);Вы должны явно использовать typing.ClassVar
, чтобы указать, что аннотированный тип предназначен только для атрибута класса. Раздел PEP 526 по аннотациям переменных класса и экземпляра определяет это поведение;на них можно положиться, а не просто на случай реализации.
Как только вы это сделаете, typing.get_type_hints
вернет {'x': int}
как для Test
, так и t
в вашем примере.
Хотя этого достаточно само по себе, я отмечу, что во многих таких случаях в настоящее время, если в любом случае вы аннотируете, вы можете упростить свой код с помощью dataclasses
модуль , получение аннотаций и основных функций, определенных для вас, с минимальным набором текста.Простой код замены для вашего дела будет выглядеть следующим образом:
import dataclasses
@dataclasses.dataclass
class Test:
x: int
Хотя в вашем деле не представлен полный набор функций (в основном это просто замена __init__
декоратором), он все же делает больше, чем кажется на первый взгляд,В дополнение к определению __init__
для вас (ожидается получение аргумента x
, который аннотируется как int
), а также подходящих __repr__
и __eq__
, вы можете легко определить значения по умолчанию (простоназначьте значение по умолчанию в точке аннотации или для более сложных или изменяемых случаев, вместо этого присвойте dataclasses.field
), и вы можете передать аргументы dataclass
, чтобы он создавал сортируемые или неизменные экземпляры.
В вашем случаеглавное преимущество заключается в устранении избыточности;x
аннотируется и ссылается ровно один раз, а не аннотируется один раз на уровне класса, а затем используется (и, возможно, снова аннотируется) во время инициализации.