如何强制施法键入命令以避免分配中的不兼容类型

发布于 2025-02-03 19:17:50 字数 984 浏览 4 评论 0原文

我正在尝试在高效率函数(试图避免复制)中执行以下(简化的示例),而无需使用Naborequired(出于此后显示的原因):

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是罪犯 - 在输出类型

i Do 不是 WANT上需要:

# 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

I am trying to do the following (simplified example) in a high efficiency function (trying to avoid copy), without using NotRequired (for reasons shown after):

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 complains about the cast as "incompatible types in assignment", but it's what I want to do. How do I achieve this? I think a is the offender - it's required on the output type

I do not want:

# kill Mytd1 
Mytd_extra = TypedDict("Mytd_extra", {x: int, z: NotRequired[str]})

because this would allow the client to pass in {x: 5, z: "asdf"} into foo but that should be forbidden - they are only allowed to pass {x: 5}.

I think the following would be doable but I'm trying to avoid it for efficiency as this function is called many times:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

您至少有两个完全有效的解决方案(假设Python 3.11不要打扰键入 vs typing_extensions,请在需要时调整导入)。问题是y是类型mytd1,因此您无法分配mytd_extra(cast的结果)。

在这里使用另一个变量

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

允许重新定义(mypy flag)

保留您的原始代码,但使用- allow-redefinition(或添加ally_redefinition = true true config config config config config您使用):

警告: allow_redefinition没有超级牛的功率,用例仅限于单个方案:当rhs中的表达式包含此变量时,将其分配到预定变量。它允许以下内容:

y = 'abc'
y = list(y)

但不是这样:

y = 'abc'
y = 1

You have at least two completely valid solutions (assuming python 3.11 not to bother with typing vs typing_extensions, adjust your imports if needed). The problem is that y is of type Mytd1, so you cannot assign Mytd_extra (result of cast) to it.

Use another variable

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

Here is a playground with this solution.

Allow redefinition (mypy flag)

Preserve your original code, but run with --allow-redefinition (or add allow_redefinition = true to config file you use): playground.

Warning: allow_redefinition does not have Super Cow Powers, it's use case is limited to a single scenario: assignment to a pre-defined variable, when expression in RHS includes this variable. It allows the following:

y = 'abc'
y = list(y)

but not this:

y = 'abc'
y = 1
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文