python - 使用 mypy,我如何键入注释一个装饰器来装饰接受某个东西的子类的函数?

标签 python types static-analysis mypy

对于完整的上下文,我希望制作一些可以更好地进行测试静态分析的装饰器。在理想的世界中,它会像这样工作:

class SomeTest(unittest.TestCase):
    @login_decorate
    def test_login(self):
        reveal_type(self.user)  # type: User

    @anonymous_decorate
    def test_anonymous(self):
        reveal_type(self.user)  # type: None

为了开始,我试图创建一个看起来像这样的装饰器:

def login_decorate(func: Callable[[unittest.TestCase], None]):
    def decorated_function(self: unittest.TestCase):
        self.user = User()
        return func(self)
    return decorated_function

但是当我运行 mypy 时出现此错误:

error: Argument 1 to "login_decorate" has incompatible type "Callable[[SomeTest], None]";
expected "Callable[[TestCase], None]"

经过一番思考,我同意由于逆变,这是 mypy 的正确行为,但这并不能帮助我解决问题。

有什么方法可以让装饰器优雅地工作,而无需使用 Any 显式修改类型?

最佳答案

你是对的,mypy 检查失败,因为 Callable 是逆变的。 它可以通过使用类型变量来修复。

import unittest
from typing import Callable, TypeVar

T = TypeVar('T', bound=unittest.TestCase)


def login_decorate(func: Callable[[T], None]):
    def decorated_function(self: T):
        ...
        return func(self)
    return decorated_function


class SomeTest(unittest.TestCase):
    @login_decorate
    def test_login(self):
        ...

关于python - 使用 mypy,我如何键入注释一个装饰器来装饰接受某个东西的子类的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59405325/

相关文章:

types - 如何从usize中减去isize?

带有对象数组和接口(interface)的 typescript 交集类型

string - 无法将HashSet <&str>强制转换为HashSet <&String>

python - 查找函数输出的输入依赖关系

python - turtle 代码被执行,但不在canvas中绘制

python - 从 python 中获取容器/父对象

security - 是否有任何工具可以对 .net 桌面程序集和可执行文件执行安全分析?

c++ - 堆栈大小估计

python - 如何将结果存储到python中的csv文件中

Python PIP 安装问题