你如何在 Python 中给一个类型起别名?
Posted
技术标签:
【中文标题】你如何在 Python 中给一个类型起别名?【英文标题】:How do you alias a type in Python? 【发布时间】:2016-01-07 19:30:40 【问题描述】:在某些(主要是函数式)语言中,您可以执行以下操作:
type row = list(datum)
或
type row = [datum]
这样我们就可以构建这样的东西:
type row = [datum]
type table = [row]
type database = [table]
有没有办法在 Python 中做到这一点?你可以使用类来实现,但是 Python 有很多功能方面,所以我想知道是否可以用更简单的方式来实现。
【问题讨论】:
相关:***.com/questions/52504347/… 有什么超级简单的东西,比如将标识符别名为 int,ID = int
工作吗?
【参考方案1】:
从 Python 3.5 开始,您可以使用 typing 模块。
引用文档, 通过将类型分配给别名来定义类型别名:
Vector = List[float]
要了解有关在 Python 中强制类型的更多信息,您可能需要熟悉 PEP:PEP483 和 PEP484。
Python 在历史上一直使用鸭子类型而不是强类型,并且在 3.5 版本之前没有内置强制类型的方法。
【讨论】:
请注意,类型提示用于静态分析和 linter 使用。类型提示不用于运行时类型检查。它们也不用于优化。另请注意,类型提示还处于起步阶段。 Python 中几乎没有代码有类型提示,也没有开发分析工具来处理它们(据我所知)。 来自 PEP484 的 Non-Goals section:“虽然提议的类型模块将包含一些用于运行时类型检查的构建块——特别是 get_type_hints() 函数——但必须开发第三方包实现特定的运行时类型检查功能,例如使用装饰器或元类。使用类型提示进行性能优化留给读者练习。” @StevenRumbalski:你忘记了mypy(它仍在开发中,但可以说是一开始就搞定了)。 我有一个函数返回Union[List[Dict[str, str]], List[Dict[str, Union[Dict[str, str], str]]]]
。你的建议很好地清理了它。
2020 年 1 月,PEP 613 是为特殊类型别名语法创建的,目前处于接受状态。不知道有没有实现。【参考方案2】:
@Lukasz 接受的答案是我们大部分时间所需要的。但是对于您需要别名本身是不同类型的情况,您可能需要使用typing.NewType
,如下所述:https://docs.python.org/3/library/typing.html#newtype
from typing import List, NewType
Vector = NewType("Vector", List[float])
一个特定的用例是,如果您正在使用 injector
库,并且您需要注入别名的新类型而不是原始类型。
from typing import NewType
from injector import inject, Injector, Module, provider
AliasRawType = str
AliasNewType = NewType("AliasNewType", str)
class MyModule(Module):
@provider
def provide_raw_type(self) -> str:
return "This is the raw type"
@provider
def provide_alias_raw_type(self) -> AliasRawType:
return AliasRawType("This is the AliasRawType")
@provider
def provide_alias_new_type(self) -> AliasNewType:
return AliasNewType("This is the AliasNewType")
class Test1:
@inject
def __init__(self, raw_type: str): # Would be injected with MyModule.provide_raw_type() which is str. Expected.
self.data = raw_type
class Test2:
@inject
def __init__(self, alias_raw_type: AliasRawType): # Would be injected with MyModule.provide_raw_type() which is str and not MyModule.provide_alias_raw_type() which is just a direct alias to str. Unexpected.
self.data = alias_raw_type
class Test3:
@inject
def __init__(self, alias_new_type: AliasNewType): # Would be injected with MyModule.provide_alias_new_type() which is a distinct alias to str. Expected.
self.data = alias_new_type
injector = Injector([MyModule()])
print(injector.get(Test1).data, "-> Test1 injected with str")
print(injector.get(Test2).data, "-> Test2 injected with AliasRawType")
print(injector.get(Test3).data, "-> Test3 injected with AliasNewType")
输出:
This is the raw type -> Test1 injected with str
This is the raw type -> Test2 injected with AliasRawType
This is the AliasNewType -> Test3 injected with AliasNewType
因此,要在使用 injector
库时正确注入正确的提供程序,您需要使用 NewType
别名。
【讨论】:
【参考方案3】:从 Python 3.10 开始,TypeAlias 注释在 typing
模块中可用。
用于显式指示已完成分配以生成类型别名。例如:
Point: TypeAlias = Tuple[float, float]
Triangle: TypeAlias = Tuple[Point, Point, Point]
您可以在介绍它的PEP 613 上阅读有关TypeAlias
注释的更多信息。
【讨论】:
以上是关于你如何在 Python 中给一个类型起别名?的主要内容,如果未能解决你的问题,请参考以下文章
oracle 如何给多表查询的结果集起别名 有一个三张表的查询语句,有数据,但加上别名后就报错了