如何强制转换类型的字典以避免分配中的不兼容类型
How to force cast typed dicts to avoid Incompatible types in assignment
我正在尝试在不使用 NotRequired
的情况下以高效功能(尽量避免复制)执行以下操作(简化示例)(原因如下所示):
Mytd1 = TypedDict("Mytd1", {a: NotRequired[str], x: int})
Mytd_extra = TypedDict("Mytd_extra", {a: str, x: int, z: str})
def foo(y: Mytd1) -> Mytd_extra:
# users input object should NOT contain z
y = cast(Mytd_extra, y). # fails - my guess is `a` is the offender
y["z"] = "hooray"
if "a" not in y:
y["a"] = "whatever"
return y
Mypy 抱怨转换为“赋值中的不兼容类型”,但这是我想要做的。我如何实现这一目标?我认为 a
是违规者 - 输出类型需要它
我不想要:
# kill Mytd1
Mytd_extra = TypedDict("Mytd_extra", {x: int, z: NotRequired[str]})
因为这将允许客户端将 {x: 5, z: "asdf"}
传递到 foo
但应该禁止 - 他们只允许传递 {x: 5}
.
我认为以下是可行的,但我试图避免它以提高效率,因为此函数被多次调用:
def foo(y: Mytd1) -> Mytd_extra:
new_var: Mytd_extra = {k: v for k:v in y.items()}
new_var["z"] = "ohno"
return new_var
你至少有两个完全有效的解决方案(假设 python 3.11 不理会 typing
vs typing_extensions
,如果需要调整你的导入)。问题是 y
的类型是 Mytd1
,所以你不能给它赋值 Mytd_extra
(强制转换的结果)。
使用另一个变量
from typing import TypedDict, NotRequired, cast
Mytd1 = TypedDict("Mytd1", {'a': NotRequired[str], 'x': int})
Mytd_extra = TypedDict("Mytd_extra", {'a': str, 'x': int, 'z': str})
def foo(orig_y: Mytd1) -> Mytd_extra:
# users input object should NOT contain z
y = cast(Mytd_extra, orig_y)
y["z"] = "hooray"
if "a" not in y:
y["a"] = "whatever"
return y
这是a playground这个解决方案。
允许重新定义(mypy 标志)
保留您的原始代码,但 运行 带有 --allow-redefinition
(或将 allow_redefinition = true
添加到您使用的配置文件):playground.
警告: allow_redefinition
没有 Super Cow Powers,它的用例仅限于一个场景:分配给 pre-defined 变量,当RHS 中的表达式包含此变量。它允许以下内容:
y = 'abc'
y = list(y)
但不是这个:
y = 'abc'
y = 1
我正在尝试在不使用 NotRequired
的情况下以高效功能(尽量避免复制)执行以下操作(简化示例)(原因如下所示):
Mytd1 = TypedDict("Mytd1", {a: NotRequired[str], x: int})
Mytd_extra = TypedDict("Mytd_extra", {a: str, x: int, z: str})
def foo(y: Mytd1) -> Mytd_extra:
# users input object should NOT contain z
y = cast(Mytd_extra, y). # fails - my guess is `a` is the offender
y["z"] = "hooray"
if "a" not in y:
y["a"] = "whatever"
return y
Mypy 抱怨转换为“赋值中的不兼容类型”,但这是我想要做的。我如何实现这一目标?我认为 a
是违规者 - 输出类型需要它
我不想要:
# kill Mytd1
Mytd_extra = TypedDict("Mytd_extra", {x: int, z: NotRequired[str]})
因为这将允许客户端将 {x: 5, z: "asdf"}
传递到 foo
但应该禁止 - 他们只允许传递 {x: 5}
.
我认为以下是可行的,但我试图避免它以提高效率,因为此函数被多次调用:
def foo(y: Mytd1) -> Mytd_extra:
new_var: Mytd_extra = {k: v for k:v in y.items()}
new_var["z"] = "ohno"
return new_var
你至少有两个完全有效的解决方案(假设 python 3.11 不理会 typing
vs typing_extensions
,如果需要调整你的导入)。问题是 y
的类型是 Mytd1
,所以你不能给它赋值 Mytd_extra
(强制转换的结果)。
使用另一个变量
from typing import TypedDict, NotRequired, cast
Mytd1 = TypedDict("Mytd1", {'a': NotRequired[str], 'x': int})
Mytd_extra = TypedDict("Mytd_extra", {'a': str, 'x': int, 'z': str})
def foo(orig_y: Mytd1) -> Mytd_extra:
# users input object should NOT contain z
y = cast(Mytd_extra, orig_y)
y["z"] = "hooray"
if "a" not in y:
y["a"] = "whatever"
return y
这是a playground这个解决方案。
允许重新定义(mypy 标志)
保留您的原始代码,但 运行 带有 --allow-redefinition
(或将 allow_redefinition = true
添加到您使用的配置文件):playground.
警告: allow_redefinition
没有 Super Cow Powers,它的用例仅限于一个场景:分配给 pre-defined 变量,当RHS 中的表达式包含此变量。它允许以下内容:
y = 'abc'
y = list(y)
但不是这个:
y = 'abc'
y = 1