Coding style 好的语义,子类还是模仿?

Coding style 好的语义,子类还是模仿?,coding-style,python,Coding Style,Python,我已经使用python有一段时间了,我很高兴在大多数表单中使用它,但我想知道哪个表单更像python。模拟对象和类型是正确的,还是从这些类型子类化或继承更好。我既看到了优点,也看到了缺点。做这件事的正确方法是什么 子类化方法 class UniqueDict(dict): def __init__(self, *args, **kwargs): dict.__init__(self, *args, **kwargs) def __setitem__(self,

我已经使用python有一段时间了,我很高兴在大多数表单中使用它,但我想知道哪个表单更像python。模拟对象和类型是正确的,还是从这些类型子类化或继承更好。我既看到了优点,也看到了缺点。做这件事的正确方法是什么

子类化方法

class UniqueDict(dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)

    def __setitem__(self, key, value):
        if key not in self:
            dict.__setitem__(self, key, value)
        else:
            raise KeyError("Key already exists")
class UniqueDict(object):
    def __init__(self, *args, **kwargs):
        self.di = dict(*args, **kwargs)

    def __setitem__(self, key, value):
        if key not in self.di:
            self.di[key] = value
        else:
            raise KeyError("Key already exists")
仿真方法

class UniqueDict(dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)

    def __setitem__(self, key, value):
        if key not in self:
            dict.__setitem__(self, key, value)
        else:
            raise KeyError("Key already exists")
class UniqueDict(object):
    def __init__(self, *args, **kwargs):
        self.di = dict(*args, **kwargs)

    def __setitem__(self, key, value):
        if key not in self.di:
            self.di[key] = value
        else:
            raise KeyError("Key already exists")

子类化更好,因为您不必为每个dict方法实现代理。

您必须在这里问自己的关键问题是:

“如果“父”类发生更改,我的类应如何更改?”


想象一下,新方法被添加到
dict
中,而您在
UniqueDict
中没有覆盖这些方法。如果您想表示
UniqueDict
只是
dict
行为中的一个小派生,那么您应该使用继承,因为您将自动获得对基类的更改。如果您想表示
UniqueDict
有点像
dict
,但实际上不是,您应该使用'emulation'模式

我会选择subclass,出于这个原因,我会提到以下动机:

例如,如果问“这个对象是什么?” 可变序列容器?',一个 可以查找“list”的基类, 或者可以查找名为 “getitem”。但请注意,尽管 这些测试可能看起来很明显,但也不是 正如一个人所产生的那样,他们中的大多数都是正确的 假阴性,另一个是假阴性 肯定的

普遍商定的补救办法是: 标准化测试,并将其分组 变成正式的安排。这是 最容易通过与 每个类别都有一套标准的可测试 属性,或者通过继承 机制或其他方式。每个 测试带有一套 承诺:它包含一个关于 类的一般行为,以及 关于其他阶级的承诺 方法将可用


简而言之,有时需要能够使用
isinstance

检查映射属性,因为您的方法并不等效。第二个实现缺少几种方法使其成为有效的映射对象methods@Jakob鲍耶:为什么要写每一个字典方法来“模仿”字典?写那些容易出错的代码有什么意义呢?嗯,但是如果你“正在”改变dict的大多数方法呢。@Jakob Bowyer:“如果你“正在”改变dict的大多数方法呢?”什么?那么这两个类都不像dict?请更新问题,解释扩展
dict
以使其不象
dict
那样是明智的做法?你到底在干什么?这是一种很好的思维方式。