Eri*_*got 31 python dictionary subclass init
这是一个双重问题,具有理论部分和实践部分:
子类化dict时:
class ImageDB(dict):
def __init__(self, directory):
dict.__init__(self) # Necessary??
...
Run Code Online (Sandbox Code Playgroud)
应该dict.__init__(self)
被称为"安全"措施(例如,如果有一些重要的非平凡实施细节)?有一个风险,即与Python的未来版本的代码休息,如果dict.__init__()
是不叫?我正在寻找做一件事或另一件事的根本原因,这里(实际上,呼叫dict.__init__()
是安全的).
我的猜测是,当ImageDB.__init__(self, directory)
调用时,self已经是一个新的空dict对象,因此无需调用dict.__init__
(我确实希望dict为空,首先).它是否正确?
编辑:
以上基本问题背后更实际的问题如下.我在考虑继承dict,因为我会经常使用db [...]语法(而不是一直使用db.contents [...]); 对象的唯一数据(属性)确实是一个字典.我想向数据库添加一些方法(例如get_image_by_name()
,或者get_image_by_code()
,例如),并且只覆盖__init__()
,因为图像数据库是由包含它的目录定义的.
总之,(实际)问题可能是:对于行为类似于字典的东西,什么是良好的实现,除了它的初始化是不同的(它只需要一个目录名),并且它有其他方法?
许多答案都提到了"工厂".所以我想这一切归结为:你是否继承dict,覆盖__init__()
和添加方法,还是你写了一个返回dict的(工厂)函数,你要添加方法?我更倾向于选择第一个解决方案,因为工厂函数返回一个对象,其类型并不表示它有其他语义和方法,但你怎么看?
编辑2:
我从每个人的回答中得知,当新类"不是字典"时,将dict子类化并不是一个好主意,特别是当它的__init__
方法不能采用与dict相同的参数时__init__
(在"实际问题"中就是这种情况)以上).换句话说,如果我理解正确,那么共识似乎是:当您进行子类化时,所有方法(包括初始化)必须与基类方法具有相同的签名.这允许isinstance(subclass_instance,dict)保证subclass_instance.__init__()
可以像dict.__init__()
例如一样使用.
然后弹出另一个实际问题:除了初始化方法之外,应该如何实现类似dict的类?没有子类?这需要一些麻烦的样板代码,不是吗?
Ala*_*oni 15
你应该dict.__init__(self)
在子类化时调用; 事实上,你不知道dict中究竟发生了什么(因为它是内置的),并且可能因版本和实现而异.不调用它可能会导致不正确的行为,因为您无法知道dict在哪里持有其内部数据结构.
顺便说一句,你没告诉我们你想做什么; 如果你想要一个带有dict(映射)行为的类,并且你真的不需要一个dict(例如isinstance(x, dict)
,你的软件中没有代码可以执行任何代码),你可能会更好地使用UserDict.UserDict
或者UserDict.DictMixin
如果你'在python <= 2.5上,或者collections.MutableMapping
如果你在python> = 2.6上.这些将为您的班级提供优秀的词典行为.
编辑:我在另一条评论中读到,你没有凌驾于任何dict的方法!然后在子类化中没有任何意义,不要这样做.
def createImageDb(directory):
d = {}
# do something to fill in the dict
return d
Run Code Online (Sandbox Code Playgroud)
编辑2:你想从dict继承添加新方法,但你不需要覆盖任何方法.比一个好的选择可能是:
class MyContainer(dict):
def newmethod1(self, args):
pass
def newmethod2(self, args2):
pass
def createImageDb(directory):
d = MyContainer()
# fill the container
return d
Run Code Online (Sandbox Code Playgroud)
顺便问一下:你在添加什么方法?你确定你正在创造一个好的抽象吗?也许你最好使用一个定义你需要的方法的类,并在内部使用一个"普通"的dict.
工厂功能:http: //en.wikipedia.org/wiki/Factory_method_pattern
它只是一种将实例的构造委托给函数而不是覆盖/更改其构造函数的方法.
Anu*_*yal 12
你通常应该调用基类' __init__
为什么在这里做一个例外?
要么不要覆盖,__init__
要么你需要覆盖__init__
调用基类__init__
,如果你担心参数只是传递*args,**kwargs或者如果你想要空的dict就没有例子,例如
class MyDict(dict):
def __init__(self, *args, **kwargs ):
myparam = kwargs.pop('myparam', '')
dict.__init__(self, *args, **kwargs )
Run Code Online (Sandbox Code Playgroud)
我们不应该假设基类正在做什么或不做什么,不调用基类是错误的 __init__
归档时间: |
|
查看次数: |
17193 次 |
最近记录: |