在python词典中指定mypy的键

问题描述 投票:3回答:2

假设我有一些代码

def get_x(d: dict) -> int:
    d["x"]

但是,我想告诉mypy,d应该只包含某些键(例如只有“x”键)。这样,如果我在代码中试图引用d的无效密钥时出错,mypy将触发错误。

我的问题是:

  1. 这可能吗? mypy可以验证字典键吗?
  2. 如果是的话,这是怎么做到的?如果不是,是否有首选的解决方法?
python python-3.x mypy python-typing
2个回答
1
投票

在尝试围绕AWS API Gateway / Lambda集成进行一些打字时也遇到了这个问题。

正如@ Michael0x2a在评论中指出的那样,TypedDict似乎是要走的路,特别是因为它在传入函数之前不需要自己进行任何转换(如你所提到的API响应的要求)。

from mypy_extensions import TypedDict

DictWithOnlyX = TypedDict('DictWithOnlyX', {"x": str})

# error: Extra key 'y' for TypedDict "DictWithOnlyX@58"
dx1: DictWithOnlyX = { "y": 123 }

# error: Incompatible types (expression has type "int",
#        TypedDict item "x" has type "str")
dx2: DictWithOnlyX = { "x": 123 }

# GOOD!
dx3: DictWithOnlyX = { "x": "123" }

还应该注意,如果依赖关系在生产和开发/测试之间被隔离,那么这使得mypy成为生产依赖。


1
投票

有几种方法并假设您的数据结构必须只具有相同的属性,但它们不使用dicts。

您可以使用namedtuple而不是传入dict。使用namedtuple,您可以将其视为对象,但也不能添加任何新字段。

from collections import namedtuple

A = namedtuple("A", ["x", "y", "z"])

def get_x(d: A) -> int:
    d.x

另一种方法是创建一个类并使用__slot__属性。这也使得不会意外插入新属性。

class A:
    __slot__ = ["x", "y", "z"]

    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

使用上述方法,您必须在一开始就定义字段。

© www.soinside.com 2019 - 2024. All rights reserved.