你如何在python中对一个类型进行别名?

Wys*_*ard 11 python alias type-hinting python-typing

在某些(主要是功能性)语言中,您可以执行以下操作:

type row = list(datum)
Run Code Online (Sandbox Code Playgroud)

要么

type row = [datum]
Run Code Online (Sandbox Code Playgroud)

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

type row = [datum]
type table = [row]
type database = [table]
Run Code Online (Sandbox Code Playgroud)

有没有办法在python中执行此操作?你可以使用类来完成它,但是python有很多功能方面,所以我想知道它是否可以更容易地完成.

Jun*_*ius 75

Python 3.10+

从 Python 3.10 开始,模块中提供了TypeAliastyping注释。

它用于显式指示已完成赋值以生成类型别名。例如:

Point: TypeAlias = tuple[float, float]
Triangle: TypeAlias = tuple[Point, Point, Point]
Run Code Online (Sandbox Code Playgroud)

您可以阅读有关介绍它的PEP 613TypeAlias上的注释的更多信息。


Nie*_*ano 34

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])
Run Code Online (Sandbox Code Playgroud)

一种特殊的用例是,如果您正在使用该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")
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

因此,为了在使用库时正确注入正确的提供程序injector,您需要NewType别名。


Łuk*_*ski 32

从Python 3.5开始,您可以使用输入模块.

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

Vector = List[float]
Run Code Online (Sandbox Code Playgroud)

要了解有关在Python中实施类型的更多信息,您可能需要熟悉PEP:PEP483PEP484.

Python历史上使用的是duck-typing而不是强类型,并且在3.5版本之前没有内置的强制类型的方式.

  • 我有一个函数返回 `Union[List[Dict[str, str]], List[Dict[str, Union[Dict[str, str], str]]]]`。你的建议对我来说非常有效,可以很好地清理它。 (4认同)
  • 请注意,类型提示用于静态分析和linters使用.类型提示不用于运行时类型检查.它们也不用于优化.另请注意,类型提示尚处于起步阶段.几乎没有Python中的代码有类型提示,也没有开发过任何分析工具来处理它们(据我所知). (3认同)

Abd*_*P M 17

Python 3.12+

Python 3.12(于 2023 年 10 月 2 日发布)包含以下实现PEP 695:类型参数语法,它提供了使用语句声明类型别名的新方法type(类似于 TypeScript)。根据文档

type语句声明了一个类型别名,它是 的实例 typing.TypeAliasType

type Point = tuple[float, float]
Run Code Online (Sandbox Code Playgroud)

类型别名也可以是通用的:

type Point[T] = tuple[T, T]
Run Code Online (Sandbox Code Playgroud)

请注意, mypy 中对 PEP 695 的支持仍在积极开发中。但确实 通过指定参数pyright支持这种语法-pythonversion 3.12

例如,pyright使用以下代码片段运行pyright myscript.py --pythonversion 3.12

# myscript.py
type vector = list[float]

def foo(items: vector):
    pass

foo(["foo", "bar"])
Run Code Online (Sandbox Code Playgroud)

将产生以下类型错误。

myscript.py:6:5 - error: Argument of type "list[str]" cannot be assigned to parameter "items" of type "vector" in function "foo"
    "Literal['foo']" is incompatible with "float"
    "Literal['bar']" is incompatible with "float" (reportGeneralTypeIssues)
1 error, 0 warnings, 0 informations 
Run Code Online (Sandbox Code Playgroud)