子类化 dict:应该调用 dict.__init__() 吗? [英] Subclassing dict: should dict.__init__() be called?

查看:33
本文介绍了子类化 dict:应该调用 dict.__init__() 吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个双重问题,一个是理论部分,一个是实践:

Here is a twofold question, with a theoretical part, and a practical one:

子类化dict时:

class ImageDB(dict):
    def __init__(self, directory):
        dict.__init__(self)  # Necessary?? 
        ...

是否应该调用 dict.__init__(self) ,作为一种安全"措施(例如,如果有一些重要的实现细节很重要)?如果dict.__init__() 被调用,是否有代码在未来版本的 Python 中中断的风险?我正在寻找做某件事的根本原因,在这里(实际上,调用 dict.__init__() 是安全的).

should dict.__init__(self) be called, just as a "safety" measure (e.g., in case there are some non-trivial implementation details that matter)? is there a risk that the code break with a future version of Python if dict.__init__() is not called? I'm looking for a fundamental reason of doing one thing or the other, here (practically, calling dict.__init__() is safe).

我的猜测是,当调用 ImageDB.__init__(self, directory) 时,self 已经是一个新的空 dict 对象,因此不需要调用 dict.__init__ (一开始我确实希望 dict 为空).这是正确的吗?

My guess is that when ImageDB.__init__(self, directory) is called, self is already a new empty dict object, and that there is therefore no need to call dict.__init__ (I do want the dict to be empty, at first). Is this correct?

编辑:

上述基本问题背后更实际的问题如下.我正在考虑对 dict 进行子类化,因为我会经常使用 db[...] 语法(而不是一直使用 db.contents[...]);对象的唯一数据(属性)确实是一个字典.我想向数据库添加一些方法(例如 get_image_by_name()get_image_by_code()),并且只覆盖 __init__(),因为图像数据库是由包含它的目录定义的.

The more practical question behind the fundamental question above is the following. I was thinking of subclassing dict because I would use the db[…] syntax quite often (instead of doing db.contents[…] all the time); the object's only data (attribute) is indeed really a dict. I want to add a few methods to the database (such as get_image_by_name(), or get_image_by_code(), for instance), and only override the __init__(), because the image database is defined by the directory that contains it.

总而言之,(实际的)问题可能是:对于像字典一样行为的东西,什么是好的实现,除了它的初始化不同(它只需要一个目录名称),以及它有其他方法吗?

In summary, the (practical) question could be: what is a good implementation for something that behaves like a dictionary, except that its initialization is different (it only takes a directory name), and that it has additional methods?

在许多答案中都提到了工厂".所以我想这一切都归结为:你是对 dict 进行子类化,覆盖 __init__() 并添加方法,还是编写一个返回 dict 的(工厂)函数,然后向其中添加方法?我更倾向于第一种解决方案,因为工厂函数返回的对象的类型并不表明它具有额外的语义和方法,但你怎么看?

"Factories" were mentioned in many answers. So I guess it all boils down to: do you subclass dict, override __init__() and add methods, or do you write a (factory) function that returns a dict, to which you add methods? I'm inclined to prefer the first solution, because the factory function returns an object whose type does not indicate that it has additional semantics and methods, but what do you think?

编辑 2:

我从每个人的回答中了解到,当新类不是字典"时,将 dict 子类化并不是一个好主意,尤其是当它的 __init__ 方法不能采用与 dict 相同的参数时__init__(上面的实际问题"就是这种情况).换句话说,如果我理解正确的话,共识似乎是:当您创建子类时,所有方法(包括初始化)都必须与基类方法具有相同的签名.例如,这允许 isinstance(subclass_instance, dict) 保证 subclass_instance.__init__() 可以像 dict.__init__() 一样使用.

I gather from everybody's answer that it is not a good idea to subclass dict when the new class "is not a dictionary", and in particular when its __init__ method cannot take the same arguments as dict's __init__ (which is the case in the "practical question" above). In other words, if I understand correctly, the consensus seems to be: when you subclass, all methods (including initialization) must have the same signature as the base class methods. This allows isinstance(subclass_instance, dict) to guarantee that subclass_instance.__init__() can be used like dict.__init__(), for instance.

接着又出现了一个实际的问题:一个和dict一样的类,除了它的初始化方法之外,应该如何实现?没有子类化?这需要一些麻烦的样板代码,不是吗?

Another practical question then pops up: how should a class which is just like dict, except for its initialization method, be implemented? without subclassing? this would require some bothersome boilerplate code, no?

推荐答案

你应该在子类化时调用 dict.__init__(self) ;事实上,您并不知道 dict 中发生了什么(因为它是内置的),而且这可能因版本和实现而异.不调用它可能会导致不当行为,因为您无法知道 dict 在哪里保存其内部数据结构.

You should probably call dict.__init__(self) when subclassing; in fact, you don't know what's happening precisely in dict (since it's a builtin), and that might vary across versions and implementations. Not calling it may result in improper behaviour, since you can't know where dict is holding its internal data structures.

顺便说一下,你没有告诉我们你想要做什么;如果您想要一个具有 dict(映射)行为的类,并且您实际上并不需要一个 dict(例如,在您的软件中的任何地方都没有代码执行 isinstance(x, dict),因为它应该是),如果您使用的是 python <= 2.5 或 collections.MutableMapping,则最好使用 UserDict.UserDictUserDict.DictMixin代码> 如果您使用的是 python >= 2.6 .这些将为您的班级提供出色的 dict 行为.

By the way, you didn't tell us what you want to do; if you want a class with dict (mapping) behaviour, and you don't really need a dict (e.g. there's no code doing isinstance(x, dict) anywhere in your software, as it should be), you're probably better off at using UserDict.UserDict or UserDict.DictMixin if you're on python <= 2.5, or collections.MutableMapping if you're on python >= 2.6 . Those will provide your class with an excellent dict behaviour.

我在另一条评论中读到您没有覆盖任何 dict 的方法!那么子类化根本没有意义,不要这样做.

I read in another comment that you're not overriding any of dict's method! Then there's no point in subclassing at all, don't do it.

def createImageDb(directory):
    d = {}
    # do something to fill in the dict
    return d

编辑 2:您想从 dict 继承以添加新方法,但您不需要覆盖任何方法.一个不错的选择可能是:

EDIT 2: you want to inherit from dict to add new methods, but you don't need to override any. Than a good choice might be:

class MyContainer(dict):
    def newmethod1(self, args):
        pass

    def newmethod2(self, args2):
        pass


def createImageDb(directory):
    d = MyContainer()
    # fill the container
    return d

顺便说一句:你要添加什么方法?你确定你正在创建一个好的抽象?也许你最好使用一个定义你需要的方法的类,并在内部使用一个正常"的字典.

By the way: what methods are you adding? Are you sure you're creating a good abstraction? Maybe you'd better use a class which defines the methods you need and use a "normal" dict internally to it.

工厂功能:http://en.wikipedia.org/wiki/Factory_method_pattern

这只是将实例的构造委托给函数而不是覆盖/更改其构造函数的一种方式.

It's simply a way of delegating the construction of an instance to a function instead of overriding/changing its constructors.

这篇关于子类化 dict:应该调用 dict.__init__() 吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆