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

173

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

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

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»? Я бы с этим согласился.)


РЕДАКТИРОВАТЬ: Ответ 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строка документации.

Если вы также зайдете в меню «Файл»> «Параметры»> «Интегрированные инструменты Python» и установите для параметра «Формат строки документа» значение «Эпитекст», то в представлении PyCharm> Быстрый поиск документации будет просто напечатана информация о параметре, а не просто напечатаны все строки @ как есть.

Джо Уайт
источник
7
Следует отметить, что для комментария reStructuredText используются одни и те же теги, только что написанные по-разному: @param xx: yyyстановится :param xx: yyy. См. Jetbrains.com/pycharm/webhelp/…
Wernight
1
Почему мы можем избежать указания полного имени класса?
Джесвин Хосе

Ответы:

85

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

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

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

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

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

CrazyCoder
источник
2
Я думаю, что PyCharm немного изменил формат документа (см. Jetbrains.com/help/pycharm/… ), но спасибо! Отсутствие интеллигентности по параметрам сводило меня с ума.
заглушки
46

Если вы используете 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

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

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

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

Feuermurmel
источник
4
... и есть несколько пакетов, которые используют такие аннотации для выполнения проверки типов во время выполнения. Это удобнее и легче читать, чем делать то же самое по утверждениям, и можно использовать выборочно точно так же. typecheck-decoratorявляется одним из таких пакетов и имеет краткое изложение других в своей документации. (Гибко, также: вы можете даже печатать на утке с проверкой типа!)
Lutz Prechelt
5

PyCharm извлекает типы из строки pydoc @type. Смотрите документы PyCharm здесь и здесь , а также документы Epydoc . Он находится в «устаревшем» разделе 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строка документации.

Мое намерение не состоит в том, чтобы украсть очки у CrazyCoder или оригинального спрашивающего, непременно дать им свои очки Я просто подумал, что простой ответ должен быть в ячейке «ответа».

dfrankow
источник
2

Я использую 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.

pongi
источник
1

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

def my_function(an_int):
    assert isinstance(an_int, int)
    # Pycharm now knows that an_int is of type int
    pass
Алехандро Даниэль Ноэль
источник