我最近发现(通过StackOverflow)调用基类中的方法我应该调用:
super([[derived class]], self).[[base class method]]()
没关系,它有效.但是,当我进行更改时,我发现自己经常在类之间复制和粘贴,而且我经常忘记将派生类参数修复为super()函数.
我想避免记得更改派生类参数.我可以改为使用self.__class__
super()函数的第一个参数吗?
它似乎有用,但有充分的理由我不应该这样做吗?
这是一个双重问题,具有理论部分和实践部分:
子类化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的类?没有子类?这需要一些麻烦的样板代码,不是吗?
我想写一个容器类
data['a']
,属性类访问,例如data.a
; 这是在这里解决的collections.OrderedDict
; 这是在这里解决的我将1.的解决方案改为子类collections.OrderedDict
而不是dict
它但不起作用; 见下文.
from collections import OrderedDict
class mydict(OrderedDict):
def __init__(self, *args, **kwargs):
super(mydict, self).__init__(*args, **kwargs)
self.__dict__ = self
D = mydict(a=1, b=2)
#D['c'] = 3 # fails
D.d = 4
#print D # fails
Run Code Online (Sandbox Code Playgroud)
带有失败注释的两行会导致以下错误:
print D
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/collections.py", line 176, in __repr__
return '%s(%r)' % (self.__class__.__name__, self.items())
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/collections.py", line 113, in items
return [(key, self[key]) for key in self] …
Run Code Online (Sandbox Code Playgroud)