键入安全的Python 3.2字典

Vec*_*tor 1 python dictionary types

在Python(3.2)中实现类型安全字典的好方法是什么 - 一个只允许将特定类型的对象添加到自身的字典?

我自己有一个简单的解决方案:使用'addItem'方法在字典周围构建一个包装类,在添加对象之前执行类型检查断言.想看看有人有更好的东西.

Gar*_*tty 7

这里的Pythonic方法是只使用普通字典,只添加特定类型的对象 - 不要试图强制执行限制,它不应该是必要的.


编辑:为了扩展我的论点,让我解释一下 - 你似乎认为编写好的代码需要类型安全.第一个问题是为什么?当然,类型安全在编译时会遇到一些错误,但根据我的经验,这些错误很少见,即使是最琐碎的测试也很容易发现,并且通常很容易修复.

相比之下,最烦人,难以修复,难以测试的错误是合乎逻辑的,计算机根本无法发现.通过制作易于理解的可读代码可以最好地防止这些问题,因此错误更加突出.动态类型通过减少代码的冗长性来大大帮助实现这一点.你可以说打字让你更容易阅读代码(因为你可以在使用时看到变量的类型),但在动态语言中,这种事情是通过仔细命名给出的 - 如果我命名一个变量seq,人们就会认为它是一个序列,可以这样使用.根据我的经验,描述性命名和良好文档的混合使动态代码更好.

归根结底,在语言中键入安全性是一个优先考虑事项,然而,Python是一种围绕鸭子打字理念设计的动态语言.语言中的所有内容都是围绕着这种方式设计的,并且尝试以另一种方式使用它将极其适得其反.如果要编写Java,请编写Java.

  • 没有语言功能可以支持它 - Python只是提供了你想要的灵活性,可以被黑客攻击做这样的事情.我还可以创建一个字典,在每个值的插入上抛出异常 - 这并不意味着它是个好主意.Python有`exec`,使用99%的东西并不是一个好主意.如果你不喜欢动态类型,那么使用一个用它构建的语言就是愚蠢的.如果你想要Java,C#或C++,那么就去使用它们,而不是编写将导致其他人头疼的'Python'. (2认同)

Mar*_*ers 5

通过分类dict和添加警卫__setitem__,.update().setdefault(); 添加一个.fromkeys()从默认值中获取类型的类方法是一个很好的额外:

from itertools import tee

class MyTypeDict(dict):
    def __init__(self, type_=SomeType, *args, **kw):
        self.type = type_
        super(MyTypeDict, self).__init__(*args, **kw)
        for val in self.itervalues():
            self._checktype(val)

    @classmethod
    def fromkeys(cls, seq, value=SomeType()):
        res = cls(type_=type(value))
        res.update((k, value) for k in seq)
        return res

    def _checktype(self, value):
        if not isinstance(value, self.type):
            raise TypeError('Value type {!r} not allowed'.format(type(value)))

    def __setitem__(self, key, value):
        self._checktype(value)
        super(MyTypeDict, self).__setitem__(key, value)

    def update(self, other):
        # Loop over other, either a dict or an iterable (use a copy with `tee`)
        # for python 3, use `items()` instead.
        items = other.iteritems() if hasattr(other, 'iteritems') else tee(other)
        for key, value in items:
            self._checktype(value)
        super(MyTypeDict, self).update(other)

    def setdefault(self, key, default=None):
        if default is None:
            default = self.type()  # assumes no-args initializer
        else:
            self._checktype(default)
        return super(MyTypeDict, self).setdefault(key, default)
Run Code Online (Sandbox Code Playgroud)

用它作为:

mydict = MyTypeDict(type_=SomeType)
Run Code Online (Sandbox Code Playgroud)