Wie kann ich PyCharm mitteilen, welcher Typ ein Parameter sein soll?

173

Wenn es um Konstruktoren, Zuweisungen und Methodenaufrufe geht, kann die PyCharm-IDE meinen Quellcode ziemlich gut analysieren und herausfinden, welcher Typ jede Variable sein sollte. Ich mag es, wenn es richtig ist, weil es mir gute Code-Vervollständigungs- und Parameterinformationen gibt und mir Warnungen gibt, wenn ich versuche, auf ein Attribut zuzugreifen, das nicht existiert.

Aber wenn es um Parameter geht, weiß es nichts. Die Dropdowns für die Code-Vervollständigung können nichts anzeigen, da sie nicht wissen, welcher Typ der Parameter sein wird. Die Code-Analyse kann nicht nach Warnungen suchen.

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

Dies macht einen gewissen Sinn. Andere Aufrufstellen könnten für diesen Parameter alles übergeben. Wenn meine Methode jedoch erwartet, dass ein Parameter vom Typ ist, pygame.Surfacemöchte ich PyCharm dies irgendwie anzeigen können, damit ich alle SurfaceAttribute in der Dropdown-Liste zur Code-Vervollständigung anzeigen und Warnungen hervorheben kann, wenn Ich nenne die falsche Methode und so weiter.

Gibt es eine Möglichkeit, PyCharm einen Hinweis zu geben und zu sagen "psst, dieser Parameter soll vom Typ X sein"? (Oder vielleicht, im Geiste dynamischer Sprachen, "soll dieser Parameter wie ein X quaken"? Damit wäre ich einverstanden.)


EDIT: Die Antwort von CrazyCoder unten macht den Trick. Für alle Neulinge wie mich, die eine kurze Zusammenfassung wünschen, ist hier:

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.

Der relevante Teil ist die @type peasant: PersonZeile der Dokumentzeichenfolge.

Wenn Sie auch zu Datei> Einstellungen> Integrierte Python-Tools gehen und "Docstring-Format" auf "Epytext" setzen, druckt PyCharms Ansicht> Schnelle Dokumentationssuche die Parameterinformationen hübsch aus, anstatt nur alle @ -Zeilen wie sie sind zu drucken.

Joe White
quelle
7
Es ist zu beachten, dass der reStructuredText-Kommentar dieselben Tags verwendet, die nur unterschiedlich geschrieben wurden: @param xx: yyywird :param xx: yyy. Siehe jetbrains.com/pycharm/webhelp/…
Wernight
1
Warum können wir davonkommen, wenn wir keinen vollständig qualifizierten Klassennamen angeben?
Jesvin Jose

Antworten:

85

Ja, Sie können ein spezielles Dokumentationsformat für Methoden und deren Parameter verwenden, damit PyCharm den Typ kennt. Die aktuelle PyCharm-Version unterstützt die meisten gängigen Dokumentformate .

PyCharm extrahiert beispielsweise Typen aus Kommentaren im @ param-Stil .

Siehe auch die Konventionen reStructuredText und docstring (PEP 257).

Eine weitere Option sind Python 3-Anmerkungen.

Weitere Informationen und Beispiele finden Sie in der PyCharm-Dokumentation .

CrazyCoder
quelle
2
Ich denke, PyCharm hat das Dokumentformat ein wenig geändert (siehe jetbrains.com/help/pycharm/… ), aber danke! Der Mangel an Intelligenz für Parameter machte mich wahnsinnig.
Stubs
46

Wenn Sie Python 3.0 oder höher verwenden, können Sie auch Anmerkungen zu Funktionen und Parametern verwenden. PyCharm interpretiert diese als den Typ, den die Argumente oder Rückgabewerte voraussichtlich haben:

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

Manchmal ist dies nützlich für nicht öffentliche Methoden, die keine Dokumentzeichenfolge benötigen. Als zusätzlichen Vorteil kann auf diese Anmerkungen per Code zugegriffen werden:

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

Update : Ab PEP 484 , das für Python 3.5 akzeptiert wurde, ist es auch die offizielle Konvention, Argument- und Rückgabetypen mithilfe von Anmerkungen anzugeben.

Feuermurmel
quelle
4
... und es gibt mehrere Pakete, die solche Antennen verwenden, um zur Laufzeit eine Typprüfung durchzuführen. Dies ist sowohl bequemer zu verwenden als auch leichter zu lesen, als dies durch Behauptungen zu tun, und kann selektiv genauso verwendet werden. typecheck-decoratorist ein solches Paket und hat eine Zusammenfassung der anderen in seiner Dokumentation. (Auch flexibel: Sie können sogar
typgeprüfte
5

PyCharm extrahiert Typen aus einer @ Typ-Pydoc-Zeichenfolge. Siehe PyCharm-Dokumente hier und hier und Epydoc-Dokumente . Es befindet sich im Abschnitt "Legacy" von PyCharm, möglicherweise fehlen einige Funktionen.

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.

Der relevante Teil ist die @type peasant: PersonZeile der Dokumentzeichenfolge.

Meine Absicht ist es nicht, CrazyCoder oder dem ursprünglichen Fragesteller Punkte zu stehlen, sondern ihnen auf jeden Fall ihre Punkte zu geben. Ich dachte nur, die einfache Antwort sollte sich in einem "Antwort" -Slot befinden.

dfrankow
quelle
2

Ich verwende PyCharm Professional 2016.1, um py2.6-2.7-Code zu schreiben, und habe festgestellt, dass ich mit reStructuredText Typen prägnanter ausdrücken kann:

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.

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

Pongi
quelle
1

Sie können auch für einen Typ behaupten, und Pycharm wird darauf schließen:

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