Como posso dizer ao PyCharm que tipo de parâmetro é esperado?

173

Quando se trata de construtores, atribuições e chamadas de método, o PyCharm IDE é muito bom em analisar meu código-fonte e descobrir qual tipo cada variável deve ser. Gosto quando está certo, porque fornece boas informações de conclusão de código e parâmetros, além de avisos se tentar acessar um atributo que não existe.

Mas quando se trata de parâmetros, nada sabe. As listas suspensas de conclusão de código não podem mostrar nada, porque não sabem que tipo de parâmetro será. A análise de código não pode procurar avisos.

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

Isso faz um certo sentido. Outros sites de chamadas podem transmitir qualquer coisa para esse parâmetro. Mas se meu método espera que um parâmetro seja do tipo, por exemplo, pygame.Surfaceeu gostaria de poder indicar isso ao PyCharm de alguma forma, para que ele possa me mostrar todos Surfaceos atributos de seu menu suspenso de conclusão de código e destacar avisos se Eu chamo o método errado e assim por diante.

Existe uma maneira de dar uma dica ao PyCharm e dizer "psst, esse parâmetro deve ser do tipo X"? (Ou talvez, no espírito das linguagens dinâmicas, "esse parâmetro deva aparecer como um X"? Eu ficaria bem com isso.)


EDIT: resposta CrazyCoder, abaixo, faz o truque. Para os novatos como eu que desejam um resumo rápido, aqui está:

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.

A parte relevante é a @type peasant: Personlinha da doutrina.

Se você também for em Arquivo> Configurações> Ferramentas Integradas do Python e definir "Formato da Docstring" como "Epytext", o Modo de Exibição do PyCharm> Pesquisa Rápida de Documentação imprimirá as informações do parâmetro em vez de apenas imprimir todas as linhas @ como estão.

Joe White
fonte
7
Note-se que o comentário reStructuredText usa as mesmas tags escritas de forma diferente: @param xx: yyytorna - se :param xx: yyy. Veja jetbrains.com/pycharm/webhelp/…
Wernight
1
Por que podemos evitar não especificar o nome completo da classe?
Jesvin Jose

Respostas:

85

Sim, você pode usar um formato de documentação especial para métodos e seus parâmetros, para que o PyCharm possa conhecer o tipo. A versão recente do PyCharm suporta os formatos mais comuns de documentos .

Por exemplo, o PyCharm extrai tipos de comentários no estilo @param .

Veja também convenções reStructuredText e docstring (PEP 257).

Outra opção são as anotações do Python 3.

Por favor, consulte a seção de documentação PyCharm para mais detalhes e amostras.

CrazyCoder
fonte
2
Acho que o PyCharm mudou um pouco o formato do documento (consulte jetbrains.com/help/pycharm/… ), mas obrigado! A falta de inteligência nos parâmetros estava me deixando louco.
Stubs
46

Se você estiver usando o Python 3.0 ou posterior, também poderá usar anotações em funções e parâmetros. O PyCharm os interpretará como o tipo que os argumentos ou valores de retorno devem ter:

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

Às vezes, isso é útil para métodos não públicos, que não precisam de uma doutrina. Como um benefício adicional, essas anotações podem ser acessadas por código:

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

Atualização : A partir do PEP 484 , aceito no Python 3.5, também é a convenção oficial especificar tipos de argumento e retorno usando anotações.

Feuermurmel
fonte
4
... e existem vários pacotes que usam essas anotações para executar a verificação de tipo em tempo de execução. Isso é mais conveniente de usar e mais fácil de ler do que fazer o mesmo por afirmações e pode ser usado seletivamente da mesma forma. typecheck-decoratoré um desses pacotes e tem um resumo dos outros em sua documentação. (Flexível, também: você pode até fazer tipagem pato verificada tipo!)
Lutz Prechelt
5

O PyCharm extrai tipos de uma cadeia de caracteres @type pydoc. Consulte os documentos PyCharm aqui e aqui e os documentos Epydoc . Está na seção 'herdada' do PyCharm, talvez não tenha alguma funcionalidade.

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.

A parte relevante é a @type peasant: Personlinha da doutrina.

Minha intenção não é roubar pontos do CrazyCoder ou do questionador original; Eu apenas pensei que a resposta simples deveria estar em um slot de 'resposta'.

dfrankow
fonte
2

Estou usando o PyCharm Professional 2016.1 escrevendo código py2.6-2.7 e descobri que usando o reStructuredText posso expressar tipos de uma maneira mais sucinta:

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.

Consulte: https://www.jetbrains.com/help/pycharm/2016.1/type-hinting-in-pycharm.html#legacy

pongi
fonte
1

Você também pode reivindicar um tipo e o Pycharm o inferirá:

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