gpt4 book ai didi

python - 类型别名和 NewType 的区别

转载 作者:行者123 更新时间:2023-12-04 15:58:31 27 4
gpt4 key购买 nike

这有什么区别:

INPUT_FORMAT_TYPE  = NewType('INPUT_FORMAT_TYPE', Tuple[str, str, str])
和这个
INPUT_FORMAT_TYPE  = Tuple[str, str, str]
从功能上讲,两者都可以工作,但像 PyCharm 这样的 IDE 标志代码如下:
return cast(INPUT_FORMAT_TYPE, ("*", "*", "All"))

最佳答案

InputFormat (重命名以保持类型符号一致)可以是 Tuple[str, str, str] 的子类型或别名.将它作为子类型(您的第一个示例)而不是别名(您的第二个示例)对于您想要静态验证(通过类似 mypy 之类的东西)所有 InputFormat 的情况很有用s 是以某种方式制作的。例如:

def new_input_format(a: str) -> InputFormat:
return InputFormat((a, a * 2, a * 4))

def print_input_format(input_format: InputFormat):
print(input_format)

print_input_format(new_input_format("a")) # Statement 1
print_input_format(("a", "aa", "aaa")) # Statement 2
InputFormat被声明为别名(通过 InputFormat = Tuple[str, str, str] ),两个语句都将静态验证。如 InputFormat被声明为子类型(通过 InputFormat = NewType('InputFormat', Tuple[str, str, str]) ),只有第一条语句会静态验证。
现在这不是万无一失的。第三条语句,例如:
print_input_format(InputFormat(("a", "aa", "aaa")))
将静态验证,但它绕过我们小心的 InputFormat创作者叫 new_input_format .但是,通过制作 InputFormat这里是一个子类型,我们被迫明确承认我们正在通过包装 tuple 来创建输入格式。在 InputFormat ,这样可以更轻松地维护此类代码并发现输入格式构造中的潜在错误。
另一个例子,其中 NewType优于类型别名:
假设你有一个数据库,我们公开了两个函数:
def read_user_id_from_session_id(session_id: str) -> Optional[str]:
...

def read_user(user_id: str) -> User:
...
打算这样称呼(图表 A):
user_id = read_user_id_by_session_id(session_id)

if user_id:
user = read_user(user_id)

# Do something with `user`.
else:
print("User not found!")
忘记我们可以在这里使用连接来使这个查询只有一个而不是两个的事实。无论如何,我们只想允许返回值 read_user_id_from_session_id用于 read_user (因为在我们的系统中,用户 ID 只能来自 session )。我们不想允许任何值,原因是它可能是一个错误。想象一下我们这样做了(图表 B):
user = read_user(session_id)
对于快速的读者来说,它可能看起来是正确的。他们可能会想到 select * from users where session_id = $1正在发生。然而,这实际上是在处理 session_id作为 user_id ,并且使用我们当前的类型提示,尽管在运行时导致意外行为,它还是通过了。相反,我们可以将类型提示更改为:
UserID = NewType("UserID", str)

def read_user_id_from_session_id(session_id: str) -> Optional[UserID]:
...

def read_user(user_id: UserID) -> User:
...
上面表达的图表 A 仍然有效,因为数据流是正确的。但是我们必须把Exhibit B变成
read_user(UserID(session_id))
这很快指出了转换 session_id 的问题到 user_id无需通过所需的功能。
在其他具有更好类型系统的编程语言中,这可以更进一步。您实际上可以禁止显式构造,例如 UserID(...)除了一个地方,所有人都必须经过那个地方,才能得到那种类型的数据。在 Python 中,您可以通过显式执行 YourNewType(...) 来绕过预期的数据流。任何地方。虽然 NewType比简单的类型别名更有利,它使这个特性成为需要。

关于python - 类型别名和 NewType 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63318719/

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