是否可以解压 类 的列表以用于 Union 类型注释?
Is it possible to unpack a list of classes for use in a Union type annotation?
我有许多映射到数据库的 SQLAlchemy ORM 类。我已经编写了很多函数,这些函数以不同的组合使用其中的许多 类。例如,我可能想从 Tournament
table 中获取第一条记录,或者从 Player
table 中获取第一条记录。我只需要一个查询,因为查询的字段在 table 之间是相同的。为了维护类型提示,我可以执行以下操作:
def get_first_record(table: Type[Union[Tournament, Player]]):
# query the table for the first record
如果我不想为其他函数重复类型提示,那么我可以创建一个变量:
Tables = Type[Union[Tournament, Player]]
def get_last_record(table: Tables):
# query the table for the last record
因为我有大量 table 并且经常添加它们,所以维护这些 Union
变量很痛苦。
巧合的是,为了锁定和解锁 table 的某些组合,我编写了一些函数来在模块中创建 类 的自定义列表。我希望在创建 Union
变量时能够解压缩这些列表,但 Pylance 告诉我 Union
需要两个以上的变量:
tables = [Tournament, Player]
Tables = Type[Union[*tables]] # no bueno :(
有解决办法吗?
我认为不可能完全按照您的要求进行操作:
tables = [Tournament, Player]
Tables = Type[Union[*tables]] # no bueno :(
有关更多详细信息,请参阅这些其他问题:
- Create Union type without hard-coding in Python3 typing
传递元组 arg(即 Union[tuple(tables)]
有效 python 并将在运行时工作,但不被任何类型检查器(例如 mypy)接受,因为您只能使用文字而不能使用表达式(即函数调用结果)用于定义类型。
可能适合您的替代方法是:
from typing import TypeVar
T = TypeVar('T', bound=django.models.Model)
def get_last_record(table: Type[T]) -> T:
...
如果您需要将 get_last_record
的调用限制为特定模型的子集,不幸的是,此注释对您没有帮助 - 您仍然需要定义 Union
个模型以用作bound
.
一个可能的变通方法是...而不是定义一个模型列表并尝试从中创建一个联合,相反,例如:
T = Union[Model1, Model2, Model3]
models = list(T.__args__)
但是既然你说 " 我已经写了一些函数来在模块中创建 classes 的自定义列表" 我认为这也不适合你因为函数调用的结果不能作为 mypy 的类型接受。
实际上,可能更适合您的是将模型联合具体化为类型层次结构,作为它们共享的基础 class。
例如而不是:
class Model1(django.models.Model):
...
class Model2(django.models.Model):
...
class Model3(django.models.Model):
...
T = Union[Model1, Model2, Model3]
def get_last_record(table: Type[T]) -> T:
...
有:
class OrderableRecord(django.models.Model):
class Meta:
abstract = True
class Model1(OrderableRecord):
...
class Model2(OrderableRecord):
...
class Model3(OrderableRecord):
...
T = TypeVar('T', bound=OrderableRecord)
def get_last_record(table: Type[T]) -> T:
...
我有许多映射到数据库的 SQLAlchemy ORM 类。我已经编写了很多函数,这些函数以不同的组合使用其中的许多 类。例如,我可能想从 Tournament
table 中获取第一条记录,或者从 Player
table 中获取第一条记录。我只需要一个查询,因为查询的字段在 table 之间是相同的。为了维护类型提示,我可以执行以下操作:
def get_first_record(table: Type[Union[Tournament, Player]]):
# query the table for the first record
如果我不想为其他函数重复类型提示,那么我可以创建一个变量:
Tables = Type[Union[Tournament, Player]]
def get_last_record(table: Tables):
# query the table for the last record
因为我有大量 table 并且经常添加它们,所以维护这些 Union
变量很痛苦。
巧合的是,为了锁定和解锁 table 的某些组合,我编写了一些函数来在模块中创建 类 的自定义列表。我希望在创建 Union
变量时能够解压缩这些列表,但 Pylance 告诉我 Union
需要两个以上的变量:
tables = [Tournament, Player]
Tables = Type[Union[*tables]] # no bueno :(
有解决办法吗?
我认为不可能完全按照您的要求进行操作:
tables = [Tournament, Player]
Tables = Type[Union[*tables]] # no bueno :(
有关更多详细信息,请参阅这些其他问题:
- Create Union type without hard-coding in Python3 typing
传递元组 arg(即 Union[tuple(tables)]
有效 python 并将在运行时工作,但不被任何类型检查器(例如 mypy)接受,因为您只能使用文字而不能使用表达式(即函数调用结果)用于定义类型。
可能适合您的替代方法是:
from typing import TypeVar
T = TypeVar('T', bound=django.models.Model)
def get_last_record(table: Type[T]) -> T:
...
如果您需要将 get_last_record
的调用限制为特定模型的子集,不幸的是,此注释对您没有帮助 - 您仍然需要定义 Union
个模型以用作bound
.
一个可能的变通方法是...而不是定义一个模型列表并尝试从中创建一个联合,相反,例如:
T = Union[Model1, Model2, Model3]
models = list(T.__args__)
但是既然你说 " 我已经写了一些函数来在模块中创建 classes 的自定义列表" 我认为这也不适合你因为函数调用的结果不能作为 mypy 的类型接受。
实际上,可能更适合您的是将模型联合具体化为类型层次结构,作为它们共享的基础 class。
例如而不是:
class Model1(django.models.Model):
...
class Model2(django.models.Model):
...
class Model3(django.models.Model):
...
T = Union[Model1, Model2, Model3]
def get_last_record(table: Type[T]) -> T:
...
有:
class OrderableRecord(django.models.Model):
class Meta:
abstract = True
class Model1(OrderableRecord):
...
class Model2(OrderableRecord):
...
class Model3(OrderableRecord):
...
T = TypeVar('T', bound=OrderableRecord)
def get_last_record(table: Type[T]) -> T:
...