Как сделать метод верхнего уровня, который возвращает себя с проверкой типа python pep484

Как можно определить функцию в классе так, чтобы возвращаемый тип функции был «текущим классом», а не базовым классом. Например:

Class Parent:
   def set_common_properties_from_string( input : str ) -> <WHAT SHOULD BE HERE>
     # Do some stuff you want to do in all classes
     return self

Class Child( Parent ):
   pass

   def from_file( filename : str ) -> 'Child'
      return Child().set_common_properties_from_string() # The return type of set_common must be Child

Или надо как-то отлить? Если возвращаемый тип — базовый класс, то будет выдана ошибка.

Я знаю, что можно было бы просто сократить его до двух строк и добавить временную переменную для хранения Child(), но я думаю, что один вкладыш выглядит намного красивее.

Я использую mypy для проверки типов.


person susundberg    schedule 21.02.2017    source источник
comment
Просто совет по стилю: пробелы после скобок и перед ними делают ваш код менее читаемым.   -  person MKesper    schedule 21.02.2017


Ответы (1)


Вы можете использовать недавно реализованный (и все еще экспериментальный) общая самостоятельная функция, представляющая собой механизм, предназначенный для решения именно той проблемы, с которой вы столкнулись.

Mypy поддерживает функцию «общего себя», начиная с версии 0.4. .6 (примечание: последняя версия mypy на момент написания — 0.470). К сожалению, я не помню, чтобы другие программы проверки типов, совместимые с PEP 484, поддерживали эту функцию.

Короче говоря, вам нужно создать новую TypeVar, явно аннотировать вашу переменную self, чтобы она имела этот тип, а также чтобы эта TypeVar была возвращаемым значением.

Итак, в вашем случае вам нужно будет изменить свой код на следующее:

from typing import TypeVar

T = TypeVar('T', bound='Parent')

class Parent:
    def set_common_properties(self: T, input: str) -> T:
        # Do some stuff you want to do in all classes
        return self

class Child(Parent):
    def from_file(self, filename: str) -> 'Child':
        # More code here
        return Child().set_common_properties(...)

Обратите внимание, что нам нужно установить, чтобы наша TypeVar была ограничена классом Parent — таким образом, в методе set_common_properties мы сможем вызывать любые другие методы, находящиеся в пределах Parent.

Вы можете найти немного больше информации на веб-сайте mypy и в PEP 484:

person Michael0x2a    schedule 26.02.2017
comment
В этом случае я бы использовал имя, отличное от T, для вашего TypeVar — заглавные буквы, например. T, U, V и т. д. по соглашению являются заполнителями для универсальных типов, но поскольку этот TypeVar явно связан с типом Parent, будет меньше путаницы, если вы назовете его, например, ParentType или что-то в этом роде. Если пользователи вашего кода увидят там T, они, скорее всего, подумают, что это общий параметр, что в данном случае не так. - person fish2000; 05.09.2018