Jak mogę określić PyCharm, jakiego typu ma być parametr?

173

Jeśli chodzi o konstruktory, przypisania i wywołania metod, IDE PyCharm jest całkiem niezłe w analizowaniu mojego kodu źródłowego i określaniu, jakiego typu powinna być każda zmienna. Podoba mi się, gdy jest to poprawne, ponieważ zapewnia mi dobre uzupełnienie kodu i informacje o parametrach oraz ostrzega mnie, gdy próbuję uzyskać dostęp do atrybutu, który nie istnieje.

Ale jeśli chodzi o parametry, to nic nie wie. Listy rozwijane uzupełniania kodu nie mogą nic pokazać, ponieważ nie wiedzą, jakiego typu będzie parametr. Analiza kodu nie może szukać ostrzeżeń.

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

Ma to pewien sens. Inne strony wywołujące mogą przekazać cokolwiek dla tego parametru. Ale jeśli moja metoda oczekuje, że parametr będzie typu, powiedzmy, pygame.Surfacechciałbym móc w jakiś sposób wskazać to PyCharm, aby mógł pokazać mi wszystkie Surfaceatrybuty w rozwijanym menu uzupełniania kodu i podświetlić ostrzeżenia, jeśli Nazywam niewłaściwą metodę i tak dalej.

Czy istnieje sposób, w jaki mogę dać PyCharm wskazówkę i powiedzieć „psst, ten parametr powinien być typu X”? (A może, w duchu języków dynamicznych, „ten parametr ma kwakać jak X”? Nie przeszkadza mi to.)


EDYCJA: odpowiedź CrazyCodera poniżej załatwia sprawę. Dla każdego nowicjusza takiego jak ja, który chce szybkiego podsumowania, oto jest:

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.

Odpowiednią częścią jest @type peasant: Personlinia dokumentu.

Jeśli również przejdziesz do Plik> Ustawienia> Zintegrowane narzędzia Python i ustawisz „Docstring format” na „Epytext”, wówczas Widok PyCharm> Szybkie wyszukiwanie dokumentacji wypisze informacje o parametrach, zamiast po prostu wydrukować wszystkie @ -lines w stanie, w jakim się znajdują.

Joe White
źródło
7
Należy zauważyć, że komentarz reStructuredText używa tych samych tagów, które zostały zapisane inaczej: @param xx: yyystaje się :param xx: yyy. Zobacz jetbrains.com/pycharm/webhelp/…
Wernight
1
Dlaczego możemy uniknąć podania w pełni kwalifikowanej nazwy klasy?
Jesvin Jose

Odpowiedzi:

85

Tak, możesz użyć specjalnego formatu dokumentacji dla metod i ich parametrów, aby PyCharm mógł znać typ. Najnowsza wersja PyCharm obsługuje większość popularnych formatów dokumentów .

Na przykład PyCharm wyodrębnia typy z komentarzy w stylu @param .

Zobacz także konwencje reStructuredText i docstring (PEP 257).

Inną opcją są adnotacje w Pythonie 3.

Więcej informacji i próbek można znaleźć w sekcji dokumentacji PyCharm .

CrazyCoder
źródło
2
Myślę, że PyCharm zmienił nieco swój format doc (patrz jetbrains.com/help/pycharm/... ), ale dzięki! Brak inteligencji parametrów doprowadzał mnie do szaleństwa.
odcinek
46

Jeśli używasz języka Python 3.0 lub nowszego, możesz również używać adnotacji do funkcji i parametrów. PyCharm zinterpretuje je jako typ, którego argumenty lub wartości zwracane powinny mieć:

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

Czasami jest to przydatne w przypadku metod niepublicznych, które nie wymagają dokumentacji. Dodatkową korzyścią jest to, że dostęp do adnotacji można uzyskać za pomocą kodu:

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

Aktualizacja : od PEP 484 , który został zaakceptowany dla Pythona 3.5, oficjalną konwencją jest również określanie argumentów i typów zwracanych za pomocą adnotacji.

Feuermurmel
źródło
4
... i istnieje kilka pakietów, które używają takich adnotacji do sprawdzania typu w czasie wykonywania. Jest to zarówno wygodniejsze w użyciu, jak i łatwiejsze do odczytania niż robienie tego samego przez asercje i może być używane wybiórczo w ten sam sposób. typecheck-decoratorjest jednym z takich pakietów i ma podsumowanie innych w swojej dokumentacji. (Elastyczne też: możesz nawet pisać kaczkę z zaznaczoną czcionką!)
Lutz Prechelt
5

PyCharm wyodrębnia typy z ciągu znaków pydoc @type. Zobacz dokumentację PyCharm tutaj i tutaj oraz dokumentację Epydoc . Znajduje się w sekcji „dziedzictwo” PyCharm, być może brakuje mu jakiejś funkcjonalności.

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.

Odpowiednią częścią jest @type peasant: Personlinia dokumentu.

Moim zamiarem nie jest kradzież punktów od CrazyCodera lub oryginalnego pytającego, z całą pewnością dawaj im ich punkty. Pomyślałem, że prosta odpowiedź powinna znajdować się w polu „odpowiedź”.

dfrankow
źródło
2

Używam PyCharm Professional 2016.1 pisząc kod py2.6-2.7 i odkryłem, że używając reStructuredText mogę wyrażać typy w bardziej zwięzły sposób:

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.

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

pongi
źródło
1

Możesz również potwierdzić typ, a Pycharm to wywnioskuje:

def my_function(an_int):
    assert isinstance(an_int, int)
    # Pycharm now knows that an_int is of type int
    pass
Alejandro Daniel Noel
źródło