我怎样才能告诉PyCharm参数期望是什么类型?

问题:我怎样才能告诉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一样嘎嘎叫”?对此我可以接受。)


编辑:下面的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集成工具”,并将“文档字符串格式”设置为“ Epytext”,则PyCharm的“视图”>“快速文档查找”将漂亮地打印参数信息,而不是仅按原样打印所有@ -lines。

When it comes to constructors, and assignments, and method calls, the PyCharm IDE is pretty good at analyzing my source code and figuring out what type each variable should be. I like it when it’s right, because it gives me good code-completion and parameter info, and it gives me warnings if I try to access an attribute that doesn’t exist.

But when it comes to parameters, it knows nothing. The code-completion dropdowns can’t show anything, because they don’t know what type the parameter will be. The code analysis can’t look for warnings.

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

This makes a certain amount of sense. Other call sites could pass anything for that parameter. But if my method expects a parameter to be of type, say, pygame.Surface, I’d like to be able to indicate that to PyCharm somehow, so it can show me all of Surface‘s attributes in its code-completion dropdown, and highlight warnings if I call the wrong method, and so on.

Is there a way I can give PyCharm a hint, and say “psst, this parameter is supposed to be of type X”? (Or perhaps, in the spirit of dynamic languages, “this parameter is supposed to quack like an X”? I’d be fine with that.)


EDIT: CrazyCoder’s answer, below, does the trick. For any newcomers like me who want the quick summary, here it is:

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.

The relevant part is the @type peasant: Person line of the docstring.

If you also go to File > Settings > Python Integrated Tools and set “Docstring format” to “Epytext”, then PyCharm’s View > Quick Documentation Lookup will pretty-print the parameter information instead of just printing all the @-lines as-is.


回答 0

是的,您可以对方法及其参数使用特殊的文档格式,以便PyCharm可以知道类型。最新的PyCharm版本支持大多数常见的doc格式

例如,PyCharm从@param样式注释中提取类型。

另请参见reStructuredTextdocstring约定(PEP 257)。

另一个选择是Python 3注释。

参阅PyCharm文档部分以获取更多详细信息和示例。

Yes, you can use special documentation format for methods and their parameters so that PyCharm can know the type. Recent PyCharm version supports most common doc formats.

For example, PyCharm extracts types from @param style comments.

See also reStructuredText and docstring conventions (PEP 257).

Another option is Python 3 annotations.

Please refer to the PyCharm documentation section for more details and samples.


回答 1

如果您使用的是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接受)开始,使用注释指定参数和返回类型也是官方约定。

If you are using Python 3.0 or later, you can also use annotations on functions and parameters. PyCharm will interpret these as the type the arguments or return values are expected to have:

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

Sometimes this is useful for non-public methods, that do not need a docstring. As an added benefit, those annotations can be accessed by code:

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

Update: As of PEP 484, which has been accepted for Python 3.5, it is also the official convention to specify argument and return types using annotations.


回答 2

PyCharm从@type pydoc字符串中提取类型。在此处此处查看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或原始提问者那里窃取分数,而应尽一切可能给予分数。我只是以为简单的答案应该在“答案”栏中。

PyCharm extracts types from a @type pydoc string. See PyCharm docs here and here, and Epydoc docs. It’s in the ‘legacy’ section of PyCharm, perhaps it lacks some functionality.

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.

The relevant part is the @type peasant: Person line of the docstring.

My intention is not to steal points from CrazyCoder or the original questioner, by all means give them their points. I just thought the simple answer should be in an ‘answer’ slot.


回答 3

我正在使用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

I’m using PyCharm Professional 2016.1 writing py2.6-2.7 code, and I found that using reStructuredText I can express types in a more succint way:

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.

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


回答 4

您还可以断言一个类型,Pycharm会推断出它:

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

You can also assert for a type and Pycharm will infer it:

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