摆脱 PyCharm 对 Python static/class 属性 的警告

Getting rid of PyCharm warning for Python static/class property

在我的 Python 2.7 程序中(抱歉,我们有一个第三方预编译的 Python 模块卡在 2.7,是的,我们依靠他们升级,是的,他们是计划到达那里),而不是只有 return TrueFalse:

的功能
foo = self.first_thing()
if not foo:
   return False
bar = self.second_thing()
if not bar:
   return False
else:
   return True

我想让调用者能够记录有关失败的详细信息。所以我创建了一个 'Result' class:

class Result(object):
   def __init__(self, success, details):
      self.success = success
      self.details = details

   def __nonzero__(self):
      return self.success

现在我可以 return 记录信息:

foo = self.first_thing()
if not foo:
   return Result(False, "first_thing failed")
bar = self.second_thing()
if not bar:
   return Result(False, "second_thing failed")
else:
   return Result(True, "")

这一切都很好。

但现在我注意到每个函数都至少构造了一个令人满意的 Result 值。所以我想提高效率,只创建一个可以随处使用的:

class Result(object):
   def __init__(self, success, details):
      self.success = success
      self.details = details

Result.Success = Result(True, "")

这很好,按预期工作:

foo = self.first_thing()
if not foo:
   return Result(False, "first_thing failed")
bar = self.second_thing()
if not bar:
   return Result(False, "second_thing failed")
else:
   return Result.Success

但是PyCharm不觉得好笑。我有这个的每个地方,PyCharm 都会给我警告 "Unresolved attribute reference 'Success' for class 'Result'".

有没有办法让 PyCharm 开心?

您可能希望为默认 'Success' 结果创建一个单独的预定义子 class 结果。

(我一开始误解了你的问题;万一有人发现这个问题并且 只是在寻找一种方法来禁用本地或全局的 PyCharm 检查;向下滚动 ).

例如:

class Result(object):
    def __init__(self, success: bool,
                       details: str):

      self.success = success
      self.details = details


class ResultSuccess(Result):

    def __init__(self, success=True,
                       details=''):

        super(Result, self).__init__(success,
                                     details)


foo = some_class.first_thing()

if not foo:
   return Result(False, "first_thing failed")
bar = some_class.second_thing()

if bar:
   return ResultSuccess()
else:
   return Result(False, "second_thing failed")

请注意,要在 Python 2.7 中使用它,您需要让基础 class 显式继承自 object,以启用新式 class 功能和 .

在Python3中不需要这个,super(Result, self).__init__(success=True, details='')可以直接换成super().__init__(success=True, details='')

防止实例化开销

由于涉及范围太广,可能会很快讨论每次实例化新对象的潜在问题,作为对 OP's 评论的回复。

在你走这条路之前,考虑在每次使用时实例化 ResultSuccess 对象是否重要。除非您快速连续地实例化它数千到数十万次,否则我认为它不太可能对大多数用例的性能产生有意义的影响(虽然还没有测试过)。此外,如果对象实例不再used/referenced,则对象实例将被垃圾回收,并且在离开它们使用的范围后不应使用内存。

如果你仍然想这样做,你可以使用一个单独的文件,即你初始化 ResultSuccess 的模块;这也意味着您不必 subclass:

# static_succesresult.py
class Result(object):

   def __init__(self, success: bool,
                      details: str):

      self.success = success
      self.details = details


ResultSuccess = Result(True, details='')

# elsewhere.py
from static_successresult import ResultSuccess

#logic which uses ResultSuccess

这应该使它成为全球性的。或者,您可以将 ResultSucces 设为 singleton in various ways(如果模块不够用,我喜欢 metaclass 的做法)。但是请注意,这种模式是有争议的。在我看来,它应该谨慎使用,原因超出了这里的范围。我认为对于像这样不应改变状态的小 class 来说很好,但可能有更好的方法来解决这个问题。 (例如,您也可以使用内置的 Enum,尽管它也使用单例。)

禁用 PyCharm 检查

您可以在设置中全局禁用特定检查。然而,人们通常不想在全球范围内这样做。

这也可以通过放置在本地完成:

# noinspection {particular_inspection_type}

... 在您想禁用它的函数或语句上方。在您的情况下,这将是:

# noinspection PyUnresolvedReferences
def function_example():
    return seemingly_unresolved_variable

# noinspection PyUnresolvedReferences
statement_example = seemingly_unresolved_variable

幸运的是,PyCharm 可以自动为您执行此操作,因此您不必记住所有检查类型的名称。

在每个文件的基础上禁用检查突出显示:

虽然不是针对特定类型的检查,但也可以针对每个文件禁用检查的突出显示; 'syntax'、'All problems' 和 'None' 是可用的选项。您可以单击右上角的警告符号,然后 select 从下拉菜单中选择所需的选项:

禁用每个语句或函数的检查:

(1) PyCharm 强调具有未解决引用的问题代码:

(2) 打开上下文菜单(默认=alt+enter):

(3) Select 在第二个上下文菜单中禁用检查(对于所需的上下文)。在这种情况下,只能选择 'suppress for statement',因为我们不在函数的上下文中:

(4) 添加了一行 PyCharm 忽略 selected 作用域的检查:

有关详细信息,请参阅 'Disabling and enabling inspections' on Jetbrain's website

下面是关于抑制 functions/statements 警告的文字描述,以防人们无法看到图像:

当您为带下划线的语句调出上下文菜单时(默认情况下应为 alt+enter,将光标置于有问题的代码处),会弹出更正问题的建议。如果您选择此项,将出现一个新的下拉菜单,要求您更正问题。如果您随后使用向右箭头或单击向右箭头以获得建议的更正,则会出现一个新的下拉菜单,其中包含“抑制语句”或“抑制函数”等选项。

选择适用于您的情况的选项以自动添加一行,指示 linter 应忽略 selected 范围的特定检查。

在你的情况下,这将是:

# noinspection PyUnresolvedReferences.

我有一段时间没有使用 PyCharm,但我认为添加类型注释可能会起作用:

from typing import ClassVar

class Result(object):
   Success: ClassVar['Result']
   def __init__(self, success, details):
      self.success = success
      self.details = details

Result.Success = Result(True, "")