是否可以根据Python中的__init__签名进行类型检查?

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

假设我有一个函数,它可以创建传入类的实例。

def instantiate[T](class_: type[T], a: int, b: str) -> T:
    return class_(a, b)

我希望类型检查器能够判断一个类是否适合这个函数,i。 e.如果它的

__init__
签名支持这样的实例。

我想使用

Protocol

class FitForInstantiate(Protocol):
    __init__: Callable[[int, str], None]

然后说类

T
必须遵守它。

def instantiate[T: FitForInstantiate](class_: type[T], a: int, b: str) -> T:
    return class_(a, b)

然后上课

class A:
    def __init__(self, a: int, b: str):
        self.a = a
        self.b = b

class B:
    def __init__(self, a: int, b: int):
        self.a = a
        self.b = b

typechecker Pyright 将接受

A
作为
instantiate
的参数,但会打印
B
的错误。但如果我随后展开
A
的签名:

class A:
    def __init__(self, a: int, b: str, c: list | None = None):
        self.a = a
        self.b = b
        self.c = c or []

它将不再遵守协议。即使它仍然对

instatiate
有用,pyright 也会为它打印一个错误。

有没有一种方法可以使用 Python 类型,以便所有具有合适

__init__
签名的类都将被视为正确的类型?

python protocols typing typechecking pyright
1个回答
0
投票

当您更改

instatiate

的签名时,这是可能的
def instantiate(class_: typing.Callable[[int,str], T], a: int, b: str) -> T:
    return class_(a, b)

(也许将 'class_' 重命名为 'constructor' 左右)

现在与

一起使用
ainst = instantiate( A, 1, 'xyz' )

binst = instantiate( B, 1, 'xyz' )  # this will trigger a type checker warning

缺点是您没有告诉类型检查器“class_”本身是一个类变量。因此,如果您想在

instantiate
中使用“class_”变量的类似类的方面,类型检查器将不允许。

好处是你也可以用它来匹配参数类型。可以作为总计(使用 ParamSpec),也可以单独使用类型变量。

© www.soinside.com 2019 - 2024. All rights reserved.