关于python:我如何告诉PyCharm参数的类型是什么?

How can I tell PyCharm what type a parameter is expected to be?

当涉及到构造函数、赋值和方法调用时,pycharm-ide非常擅长分析源代码并找出每个变量应该是什么类型。我喜欢它是正确的,因为它给我很好的代码完成和参数信息,如果我试图访问一个不存在的属性,它会给我警告。

但当涉及到参数时,它什么也不知道。代码完成下拉列表不能显示任何内容,因为它们不知道参数的类型。代码分析无法查找警告。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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的答案。对于像我这样想要快速总结的新来者,这里是:

1
2
3
4
5
6
7
8
9
10
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.

相关部分是docstring的@type peasant: Person行。

如果您还转到"文件>设置>Python集成工具"并将"docstring格式"设置为"epytext",那么pycharm的"视图>快速文档查找"将漂亮地打印参数信息,而不是按原样打印所有@行。


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

例如,pycharm从@param-style注释中提取类型。

另请参见RestructuredText和DocString约定(PEP 257)。

另一个选项是python 3注释。

有关更多详细信息和示例,请参阅Pycharm文档部分。


如果您使用的是python 3.0或更高版本,那么也可以在函数和参数上使用注释。pycharm将把这些解释为参数或返回值应该具有的类型:

1
2
3
4
5
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

有时这对于不需要docstring的非公共方法很有用。作为一个额外的好处,这些注释可以通过代码访问:

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

更新:从已经被Python3.5接受的PEP484开始,使用注释指定参数和返回类型也是一种正式的约定。


pycharm从@type pydoc字符串中提取类型。看看这里和这里的pycharm文档,还有epydoc文档。它在Pycharm的"遗留"部分,也许它缺少一些功能。

1
2
3
4
5
6
7
8
9
10
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.

相关部分是docstring的@type peasant: Person行。

我的目的不是从Crazycoder或最初的提问者那里窃取分数,而是尽一切办法给他们分数。我只是觉得简单的答案应该在"答案"位置。


你也可以为一个类型断言,Pycharm会推断它:

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

我正在使用pycharm professional 2016.1编写py2.6-2.7代码,我发现使用restructuredtext可以更简洁地表达类型:

1
2
3
4
5
6
7
8
9
10
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