是否可以向代码之外的函数添加类型注释?

问题描述 投票:0回答:1

假设我正在为一个不受我控制的大型遗留代码库编写一个 Python 插件。该代码库公开了一个具有多个函数的对象,我可以从我的插件代码中调用这些函数:

def plugin_entrypoint(ctx: LegacyCodebaseObject):
   ...

这些函数之一会导致插件控制器以错误条件终止插件:

def plugin_entrypoint(ctx: LegacyCodebaseObject):
   ...
   ctx.fail(reason="foo", ...)  # never returns

但是,作为遗留代码库,这些函数都没有类型注释。我的插件 is 类型注释,并且我使用 mypy,这会引起烦恼,因为 mypy 认为

ctx.fail()
可能会返回:

def plugin_entrypoint(ctx: LegacyCodebaseObject):
   ...
   try:
      some_data = some_function()
   except Exception as e:
      ctx.fail(reason=f"Failed to prepare data: {e}")  # never returns

   other_function(some_data)  # mypy complains that some_data might be referenced before assignment

是否可以在我的代码中以 mypy 能够理解的方式注释

LegacyCodebaseObject.fail()

我可以简单地将

ctx.fail()
包装到我自己的函数中,并用 Never type 进行注释,但这将是不符合语法的,而且我的插件将无法通过代码审查。

python type-hinting
1个回答
0
投票

一种方法是利用

TYPE_CHECKING
和继承。

我们假设遗留代码如下所示:

# Deep inside the legacy code base
class LegacyCodebaseObject:

  def foo(self):
    ...

  def bar(self, baz, *, qux):
    ...

  def fail(self):
    raise Exception

TYPE_CHECKING
分支中,使用别名将其导入到您的代码中,然后使用正确的名称创建一个子类:

if TYPE_CHECKING:
  from legacy_codebase import LegacyCodebaseObject as _LegacyCodebaseObject

  class LegacyCodebaseObject(LegacyCodebaseObject):

    # Correct type hints here
    def fail(self, reason: str, **kwargs: Any) -> Never:
      ...

    # Other methods as well
    ...

在另一个分支上,只需正常导入即可:

else:
  from legacy_codebase import LegacyCodebaseObject
© www.soinside.com 2019 - 2024. All rights reserved.