gpt4 book ai didi

Python3 typehints - 传入类型的元组后,指定返回值是这些类型的实例的元组

转载 作者:行者123 更新时间:2023-11-30 22:11:18 24 4
gpt4 key购买 nike

我目前使用一些复杂的类型提示来实现我使用sqlalchemy 为 dB 调用所做的“快捷方式”函数。例如,不必编写,

users: List[User] = User.query.all()

我在基本模型中创建了一个快捷函数,

@classmethod
def qall(cls: Type[T_DBModel]) -> List[T_DBModel]:
cls.query.all()

所以现在我可以写 users = User.qall() 并且 typehint 对于我的 IDE (PyCharm) 来说就像一个魅力 - 它正确地识别出这将是 List[User ] 无需我指定。

现在,我想对 sqlalchemywith_entities 函数执行相同的操作。这样,您可以指定希望 dB 调用返回一个元组,即

users_roles: List[Tuple[User, Role]] = User.query.with_entities(User, Role).all()

我想为此编写一个与上面类似的快捷方法,

@classmethod
def qwith_entities(cls: Type[T_DBModel], retvals: T) -> List[T]:
cls.query.with_entities(*retvals).all()

所以我可以“快捷方式”以同样的方式使用它,

users_roles = User.qwith_entities((User, Role))

问题是,使用该签名时,指定返回 List[Tuple[User, Role]] 的不是 typehint,而是 List[Tuple[Type[User], Type[Role] ]]] 这是不正确的,并且不是返回值。

如果我把它分解成多个函数,那一切都很好,

@classmethod
def qwith_entity(cls: Type[T_DBModel], retval: Type[T]) -> List[T]:
cls.query.with_entities(retval).all()

它知道Base.qwith_entity(User)将是List[User](你永远不会这样做,只是一个例子)和

@classmethod
def qwith_2_entities(cls: Type[T_DBModel], retval_1: Type[T], retval_2: Type[Y]) -> List[Tuple[T, Y]]:
cls.query.with_entities(retval_1, retval_2).all()

@classmethod
def qwith_2_entities(cls: Type[T_DBModel], retvals: Tuple[Type[T], Type[Y]]) -> List[Tuple[T, Y]]:
cls.query.with_entities(*retvals).all()

哪个知道users_roles = Base.qwith_2_entities((User, Role))将是List[Tuple[User, Role]]

但我不知道如何操作,也不知道是否可以正确键入不同 Type变量长度Tuple,并且返回值应该解压它,即像这样愚蠢的东西,

@classmethod
def qwith_entities(cls: Type[T_DBModel], retvals: Tuple[Type[...T]]) -> List[Tuple[T]]:
cls.query.with_entities(*retvals).all()

最佳答案

您需要variadic generics以便您准确拼出签名; 这还不可能,但它可能看起来像:

Ts = TypeVar('Ts', variadic=True)

@classmethod
def qwith_2_entities(cls: Type[T_DBModel], retvals: Tuple[Type[Ts], ...]) -> List[Tuple[Ts, ...]]:
cls.query.with_entities(*retvals).all()

其中 Ts TypeVar 是可变参数,Tuple[Type[Ts], ...] 扩展为表示 Tuple[Type[T_0], Type[T_1], Type[T_2], ...]) 并且返回列表中的类型被扩展为表示 Tuple[T_0, T_1, T_2, .. .])

但是,正如前面提到的,这还不是可用的语法。解决方法是将 @overload 与 1、2、3 等不同的 TypeVar 一起使用,至少足以满足您的所有用例:

T1 = TypeVar('T1')
T2 = TypeVar('T2')
T3 = TypeVar('T3')
T4 = TypeVar('T4')
# add more as needed

@overload
def qwith_2_entities(cls: Type[T_DBModel], retvals: Tuple[Type[T1]]) -> List[Tuple[T1]]:
pass
@overload
def qwith_2_entities(cls: Type[T_DBModel], retvals: Tuple[Type[T1], Type[T2]]) -> List[Tuple[T1, T2]]:
pass
@overload
def qwith_2_entities(cls: Type[T_DBModel], retvals: Tuple[Type[T1], Type[T2], Type[T3]]) -> List[Tuple[T1, T2, T3]]:
pass
@overload
def qwith_2_entities(cls: Type[T_DBModel], retvals: Tuple[Type[T1], Type[T2], Type[T3], Type[T4]]) -> List[Tuple[T1, T2, T3, T4]]:
pass
# add more overloads as needed
@classmethod
def qwith_2_entities(cls, retvals):
cls.query.with_entities(*retvals).all()

关于Python3 typehints - 传入类型的元组后,指定返回值是这些类型的实例的元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51456539/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com