python - 如何对字典进行子类化,使其支持通用类型提示?

标签 python python-3.x dictionary type-hinting mypy

如何对字典进行子类化,以使子类支持通用类型提示?它在所有方面都需要像字典一样工作,并支持键和值的类型提示。子类将添加访问和操作字典数据的函数。例如,它将具有valueat(self, idx:int)函数,该函数返回给定索引处的字典值。
它不需要OrderedDict作为其基类,但是字典确实需要具有可预测的顺序。由于OrderedDict保持插入顺序并支持类型提示,因此这似乎是一个合理的起点。
这是我尝试过的:

from collections import OrderedDict

class ApplicationSpecificDict(OrderedDict[str, int]):
    ...
但是,它失败并显示以下错误:TypeError: 'type' object is not subscriptablePython 3.7+不支持此功能吗?或者我缺少某些功能吗?

最佳答案

typing包提供了与collections.abccollections中的非泛型类相对应的泛型类。这些通用类可以用作创建用户定义的通用类(例如自定义通用字典)的基类。
collections.abc中的类型相对应的泛型类的示例:

  • typing.AbstractSet(Sized, Collection[T_co])
  • typing.Container(Generic[T_co])
  • typing.Mapping(Sized, Collection[KT], Generic[VT_co])
  • typing.MutableMapping(Mapping[KT, VT])
  • typing.MutableSequence(Sequence[T])
  • typing.MutableSet(AbstractSet[T])
  • typing.Sequence(Reversible[T_co], Collection[T_co])

  • collections中的类型相对应的泛型类的示例:
  • typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])
  • typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])
  • typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT])
  • typing.Counter(collections.Counter, Dict[T, int])
  • typing.Deque(deque, MutableSequence[T])

  • 实现自定义的通用字典
    有许多实现自定义通用词典的选项。但是,请务必注意,除非用户定义的类显式继承自MappingMutableMapping,否则像mypy这样的静态类型检查器将不会将该类视为映射。
    用户定义的通用字典示例
    from collections import abc  # Used for isinstance check in `update()`.
    from typing import Dict, Iterator, MutableMapping, TypeVar
    
    KT = TypeVar('KT')
    VT = TypeVar('VT')
    
    
    class MyDict(MutableMapping[KT, VT]):
    
        def __init__(self, dictionary=None, /, **kwargs) -> None:
            self.data: Dict[KT, VT] = {}
            if dictionary is not None:
                self.update(dictionary)
            if kwargs:
                self.update(kwargs)
        
        def __contains__(self, key: KT) -> bool:
            return key in self.data
    
        def __delitem__(self, key: KT) -> None:
            del self.data[key]
    
        def __getitem__(self, key: KT) -> VT:
            if key in self.data:
                return self.data[key]
            raise KeyError(key)
    
        def __len__(self) -> int:
            return len(self.data)
    
        def __iter__(self) -> Iterator[KT]:
            return iter(self.data)
    
        def __setitem__(self, key: KT, value: VT) -> None:
            self.data[key] = value
        
        @classmethod
        def fromkeys(cls, iterable: Iterable[KT], value: VT) -> "MyDict":
            """Create a new dictionary with keys from `iterable` and values set 
            to `value`.
    
            Args:
                iterable: A collection of keys.
                value: The default value. All of the values refer to just a single 
                    instance, so it generally does not make sense for `value` to be a 
                    mutable object such as an empty list. To get distinct values, use 
                    a dict comprehension instead.
    
            Returns:
                A new instance of MyDict.
            """
            d = cls()
            for key in iterable:
                d[key] = value
            return d
    
        def update(self, other=(), /, **kwds) -> None:
            """Updates the dictionary from an iterable or mapping object."""
            if isinstance(other, abc.Mapping):
                for key in other:
                    self.data[key] = other[key]
            elif hasattr(other, "keys"):
                for key in other.keys():
                    self.data[key] = other[key]
            else:
                for key, value in other:
                    self.data[key] = value
            for key, value in kwds.items():
                self.data[key] = value
    
    

    关于python - 如何对字典进行子类化,使其支持通用类型提示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61112684/

    相关文章:

    python - 在多个 Python worker 之间共享 Postgres 表中指定的工作

    python - 如何减少anaconda目录下的文件数量?

    python - 导入错误: No module named

    python - 如何使用 Selenium 查找网页中元素的位置?

    python - 计算列表中单词的频率并按频率排序

    c++ - 如何更改 map 中的默认整数值?

    Python 文件上传小部件不工作,它没有在 jupyter notebook 中显示上传按钮

    python-3.x - 二维数据的 numpy 条件函数

    c# - 最有效的 Dictionary<K,V>.ToString() 格式?

    c++ - 为 map 重载 '<' 运算符时遇到问题