如何在Python中为类型设置别名?

88

在某些(主要是函数式)语言中,您可以像这样做:

type row = list(datum)


type row = [datum]

这样我们就可以构建像这样的东西:

type row = [datum]
type table = [row]
type database = [table]

有没有一种方法可以在Python中实现这个?您可以使用类来做到这一点,但是Python具有相当多的函数方面,因此我想知道是否有更简单的方法可以实现。

有没有一种更简单的方法在 Python 中实现这个?尽管你可以使用类来完成,但是 Python 具有许多函数式方面的特性。

1
相关:https://dev59.com/elQK5IYBdhLWcg3wEr8X - mic
关于编程的内容,将以下文本从英语翻译为中文。只返回翻译后的文本:要不要尝试一些非常简单的东西,比如将标识符别名为整数,ID = int 这样行吗? - Charlie Parker
5个回答

170

Python 3.5+

自从Python 3.5版本以后,你可以使用typing模块。

引用文档, 类型别名通过将类型赋值给别名来定义:

# Python 3.5-3.8
from typing import List
Vector = List[float]

# Python 3.9+
Vector = list[float] # No import needed, lower case l

要了解如何在Python中强制类型,您可能希望熟悉PEP(Python增强提案):PEP483PEP484
在3.5版本发布之前,Python在历史上使用的是鸭子类型而不是强类型,并且没有内置的声明类型的方法。

6
请注意,类型提示旨在用于静态分析和供代码检查工具使用。类型提示不用于运行时类型检查,也不用于优化。请注意,类型提示尚处于起步阶段,在 Python 中几乎没有代码使用类型提示,并且(据我所知)没有开发出处理它们的分析工具。 - Steven Rumbalski
1
从 PEP484 的 Non-Goals section 中可以了解到:虽然建议的类型模块将包含一些运行时类型检查的构建块——特别是 get_type_hints() 函数——但第三方包必须被开发来实现特定的运行时类型检查功能,例如使用装饰器或元类。将类型提示用于性能优化留给读者自己去练习。 - Steven Rumbalski
1
@StevenRumbalski:你忘了mypy(它仍在开发中,但可以说它才是开始这整个球滚动的东西)。 - Kevin
4
我曾有一个函数返回的是 Union[List[Dict[str, str]], List[Dict[str, Union[Dict[str, str], str]]]]。你提供的建议极大地帮助我整理了这个函数,使其更加清晰易懂。 - grooveplex
1
@CharlieParker在https://dev59.com/elQK5IYBdhLWcg3wEr8X#52512686中解释了该方法可能存在的问题。 - Nuclear03020704
显示剩余5条评论

58

Python 3.10+

自从Python 3.10版本以后,TypeAlias注解在typing模块中可用。

它用于明确表示赋值是用于生成类型别名的。例如:

Point: TypeAlias = tuple[float, float]
Triangle: TypeAlias = tuple[Point, Point, Point]

你可以在引入它的PEP 613上阅读更多关于TypeAlias注解的内容。

3
不过,Tuple 应该是小写字母吧?我记得在一些较新的 PEP 中看到过这样的写法。 - 303
1
当然!我会纠正它。 - Jundiaius
8
实际上,小写的 tuple[...] 是一个相对比较新的特性。Tuple 可以与至少 Python 3.6 兼容。因此,如果使用 Python < 3.10,可以将显式类型别名注释为 Point: 'TypeAlias' = Tuple[float, float] - MestreLion

30

Python 3.5+

大多数情况下,我们需要的是@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别名。

谢谢,这是迄今为止最好的答案。我以前是使用其他答案中解释的“经典”类型别名,但类型检查器实际上并没有将其识别为类型。这个方法可行! - ThR37

9

-2

Python 3.10+

这是使用现代的Python 3.10完成的。

❯ python
Python 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> Array = list
>>> a = Array()
>>> a.append(1)
>>> a.append(2)
>>> a.append(3)
>>> a
[1, 2, 3]
>>>

这个问题并不是关于如何在Python中创建列表的。这个答案没有提供任何关于类型别名的信息。 - undefined
1
@The_spider 我认为这个想法是将列表别名为"Array"。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接