Как я могу сказать PyCharm, какой тип должен быть параметром?

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

Но когда дело доходит до параметров, он ничего не знает. Выпадающие списки завершения кода ничего не могут показать, потому что они не знают, какой тип будет иметь параметр. Анализ кода не может искать предупреждения.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

peasant = Person("Dennis", 37)
# PyCharm knows that the "peasant" variable is of type Person
peasant.dig_filth()   # shows warning -- Person doesn't have a dig_filth method

class King:
    def repress(self, peasant):
        # PyCharm has no idea what type the "peasant" parameter should be
        peasant.knock_over()   # no warning even though knock_over doesn't exist

King().repress(peasant)
# Even if I call the method once with a Person instance, PyCharm doesn't
# consider that to mean that the "peasant" parameter should always be a Person

Это делает определенный смысл. Другие сайты вызовов могут передавать что-либо для этого параметра. Но если мой метод ожидает, что параметр имеет тип, скажем, pygame.Surface, я хотел бы указать, что PyCharm каким-то образом, поэтому он может показать мне все атрибуты Surface в раскрывающемся списке завершения кода, и выделять предупреждения, если я вызываю неправильный метод и т.д.

Есть ли способ дать PyCharm подсказку и сказать "psst, этот параметр должен быть типа X"? (Или, может быть, в духе динамических языков, "этот параметр должен одурачить, как X"? Мне было бы хорошо с этим.)


EDIT: Ответ CrazyCoder, ниже, делает трюк. Для любых новичков, таких как я, которые хотят краткое резюме, вот оно:

class King:
    def repress(self, peasant):
        """
        Exploit the workers by hanging on to outdated imperialist dogma which
        perpetuates the economic and social differences in our society.

        @type peasant: Person
        @param peasant: Person to repress.
        """
        peasant.knock_over()   # Shows a warning. And there was much rejoicing.

Соответствующая часть - это строка @type peasant: Person docstring.

Если вы также перейдете в меню "Файл" > "Настройки" > "Интегрированные инструменты на Python" и установите "Формат Docstring" в "Epytext", тогда PyCharm View > Quick Documentation Lookup будет довольно печатать информацию о параметрах, а не просто печатать все @-lines как -is.

Ответ 1

Да, вы можете использовать специальный формат документации для методов и их параметров, чтобы PyCharm мог знать тип. Недавняя версия PyCharm поддерживает большинство распространенных форматов doc.

Например, PyCharm извлекает типы из @комментариев стиля param.

См. также reStructuredText и соглашения docstring (PEP 257).

Другой вариант - аннотации Python 3.

Пожалуйста, обратитесь к разделу документации PyCharm для получения более подробной информации и образцов.

Ответ 2

Если вы используете Python 3.0 или новее, вы также можете использовать аннотации для функций и параметров. PyCharm будет интерпретировать их как тип, который должен иметь аргумент или возвращаемые значения:

class King:
    def repress(self, peasant: Person) -> bool:
        peasant.knock_over() # Shows a warning. And there was much rejoicing.

        return peasant.badly_hurt() # Lets say, its not known from here that this method will always return a bool

Иногда это полезно для непубличных методов, для которых не требуется docstring. В качестве дополнительной выгоды эти аннотации можно получить по коду:

>>> King.repress.__annotations__
{'peasant': <class '__main__.Person'>, 'return': <class 'bool'>}

Обновить. Что касается PEP 484, который был принят для Python 3.5, это также официальное соглашение для указания типов аргументов и возвращаемых значений с помощью аннотаций.

Ответ 3

PyCharm извлекает типы из строки @type pydoc. См. PyCharm docs здесь и здесь и Epydoc docs. Это в разделе "legacy" PyCharm, возможно, ему не хватает функциональности.

class King:
    def repress(self, peasant):
        """
        Exploit the workers by hanging on to outdated imperialist dogma which
        perpetuates the economic and social differences in our society.

        @type peasant: Person
        @param peasant: Person to repress.
        """
        peasant.knock_over()   # Shows a warning. And there was much rejoicing.

Соответствующая часть - это строка @type peasant: Person docstring.

Мое намерение состоит не в том, чтобы украсть очки у CrazyCoder или у оригинального опросника, дайте им все свои очки. Я просто подумал, что простой ответ должен быть в слоте "ответ".

Ответ 4

Вы также можете утверждать, что тип и Pycharm выведут его:

def my_function(an_int):
    assert isinstance(an_int, int)
    # Pycharm now knows that an_int is of type int
    pass

Ответ 5

Я использую PyCharm Professional 2016.1, пишущий код py2.6-2.7, и я обнаружил, что с помощью reStructuredText я могу выражать типы более сукцитовым способом:

class Replicant(object):
    pass


class Hunter(object):
    def retire(self, replicant):
        """ Retire the rogue or non-functional replicant.
        :param Replicant replicant: the replicant to retire.
        """
        replicant.knock_over()  # Shows a warning.

Смотрите: https://www.jetbrains.com/help/pycharm/2016.1/type-hinting-in-pycharm.html#legacy