我如何告诉 PyCharm 参数应该是啥类型?

Posted

技术标签:

【中文标题】我如何告诉 PyCharm 参数应该是啥类型?【英文标题】:How can I tell PyCharm what type a parameter is expected to be?我如何告诉 PyCharm 参数应该是什么类型? 【发布时间】:2011-09-13 05:05:59 【问题描述】:

当涉及到构造函数、赋值和方法调用时,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 集成工具”并将“Docstring 格式”设置为“Epytext”,那么 PyCharm 的“视图”>“快速文档查找”将漂亮地打印参数信息,而不仅仅是将所有 @-lines 打印为-是。

【问题讨论】:

需要注意的是,reStructuredText 注释使用相同的标签,只是写法不同:@param xx: yyy 变为:param xx: yyy。见jetbrains.com/pycharm/webhelp/… 为什么我们可以不指定完全限定的类名? 【参考方案1】:

是的,您可以对方法及其参数使用特殊的文档格式,以便 PyCharm 可以知道类型。最近的 PyCharm 版本supports most common doc formats。

例如,PyCharm 从@param style comments 中提取类型。

另请参阅 reStructuredText 和 docstring conventions (PEP 257)。

另一个选项是 Python 3 注释。

请refer to the PyCharm documentation section了解更多详情和样品。

【讨论】:

我认为 PyCharm 稍微改变了它的文档格式(参见jetbrains.com/help/pycharm/…),但谢谢!参数上缺乏智能感知让我发疯。【参考方案2】:

如果您使用的是 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'>

更新:从 Python 3.5 接受的 PEP 484 开始,使用注解指定参数和返回类型也是官方约定。

【讨论】:

...并且有几个包使用这样的注释来执行运行时类型检查。这比通过断言做同样的事情更方便使用和更容易阅读,并且可以选择性地使用。 typecheck-decorator 就是这样一个包,并且在其文档中有其他包的摘要。 (也很灵活:你甚至可以进行类型检查的鸭子打字!)【参考方案3】:

PyCharm 从@type pydoc 字符串中提取类型。请参阅PyCharm 文档here 和here,以及Epydoc docs。它位于 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 或最初的提问者那里窃取分数,一定要给他们他们的分数。我只是认为简单的答案应该在“答案”槽中。

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

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

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

【讨论】:

以上是关于我如何告诉 PyCharm 参数应该是啥类型?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 python *.py 之前使用命令在 pycharm 中调试?

Pycharm:“在 'image.py' 中找不到参考 'load'”

我应该如何在Pycharm中去运行别人的Django项目

pycharm unused import statement 是啥原因?

Django:如何告诉 Django 它应该在哪里寻找应用程序?

如何配置 PyCharm 以运行 py.test 测试?